{"id":208,"date":"2014-08-05T13:58:23","date_gmt":"2014-08-05T16:58:23","guid":{"rendered":"http:\/\/arielnavarrete.wordpress.com\/2014\/08\/05\/castear-un-string-a-entero-con-doctrine\/"},"modified":"2014-08-05T13:58:23","modified_gmt":"2014-08-05T16:58:23","slug":"castear-un-string-a-entero-con-doctrine","status":"publish","type":"post","link":"https:\/\/arielnavarrete.cl\/blog\/2014\/08\/05\/castear-un-string-a-entero-con-doctrine\/","title":{"rendered":"Castear un String a Entero con Doctrine"},"content":{"rendered":"<p>El problema es el siguiente, teniendo un campo String en donde se guarda un campo numerico se requeria ordenar por este, al ser String se ordenaba de una manera \u00abincorrecta\u00bb, en cierto modo es correcto pero dado el contenido no era lo esperado por el Usuario. Lo mas logico seria dejar este campo como Entero y listo, pero el problema es que la Base de Datos contiene mucha informacion y la persona que la hizo en su momento lo definio asi, por lo tanto, no nos dejaron cambiarla, asi que asumimos que seria asi.<\/p>\n<p>Y bueno, buscando informacion sobre como castear un string a entero con Doctrine 2 en Symfony 2, no encontre ninguna forma directa ya que por lo visto no existe, la unica forma que logre encontrar es creando una funcion personalizada.<\/p>\n<p><!--more Seguir Leyendo...--><\/p>\n<p>Guiandome sobre este post encontrado en\u00a0<a title=\"stackoverflow\" href=\"http:\/\/stackoverflow.com\/questions\/7405342\/casting-attributes-for-ordering-on-a-doctrine2-dql-query\" target=\"_blank\">stackoverflow<\/a> realizamos lo siguiente:<\/p>\n<p>1) Creamos el archivo <strong>CastAsInteger<\/strong><\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">&amp;lt;?php\n\nnamespace AN\\PruebaBundle\\Query;\n\nuse Doctrine\\ORM\\Query\\AST\\Functions\\FunctionNode;\nuse Doctrine\\ORM\\Query\\Lexer;\nuse Doctrine\\ORM\\Query\\Parser;\nuse Doctrine\\ORM\\Query\\SqlWalker;\n\nclass CastAsInteger extends FunctionNode\n{\n\u00a0\u00a0\u00a0 public $stringPrimary;\n\n\u00a0\u00a0\u00a0 public function getSql(SqlWalker $sqlWalker)\n\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return &#039;CAST(&#039; . $this-&amp;gt;stringPrimary-&amp;gt;dispatch($sqlWalker) . &#039; AS UNSIGNED INTEGER)&#039;;\n\u00a0\u00a0\u00a0 }\n\n\u00a0\u00a0\u00a0 public function parse(Parser $parser)\n\u00a0\u00a0\u00a0 {\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $parser-&amp;gt;match(Lexer::T_IDENTIFIER);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $parser-&amp;gt;match(Lexer::T_OPEN_PARENTHESIS);\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&amp;gt;stringPrimary = $parser-&amp;gt;StringPrimary();\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $parser-&amp;gt;match(Lexer::T_CLOSE_PARENTHESIS);\n\u00a0\u00a0\u00a0 }\n}<\/pre>\n<p>Tiene algunas peque\u00f1as cosas distintas con respecto al original del Post, ya que no funcionaba el de dicho Post probado en Symfony 2.3.18<\/p>\n<p>&nbsp;<\/p>\n<p>2) Cargamos nuestra nueva funci\u00f3n a la configuraci\u00f3n de Doctrine<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">$config = $this-&amp;gt;em-&amp;gt;getConfiguration();\n$config-&amp;gt;addCustomNumericFunction(&#039;INT&#039;, &#039;AN\\PruebaBundle\\Query\\CastAsInteger&#039;);<\/pre>\n<p>&nbsp;<\/p>\n<p>3) La forma de ocuparlo seria como se indica en dicho POST<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">$dql = &amp;quot;SELECT a, INT(a.folio) AS HIDDEN orderId\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0FROM ANPruebaBundle:Aviso a\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0ORDER BY orderId ASC&amp;quot;;\n\n$query = $em-&amp;gt;createQuery($dql);\n\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Ahora bien, si ocuparemos esto muchas veces, creo que estar cargando cada vez la configuraci\u00f3n no es lo mas optimo, asi que crearemos un servicio, para ello haremos lo siguiente:<\/p>\n<p>1) Creamos el archivo <strong>Doctrine<\/strong><\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">&amp;lt;?php\n\/\/Ruta donde lo creamos\nnamespace AN\\PruebaBundle\\Services;\n\nuse Symfony\\Component\\DependencyInjection\\ContainerInterface;\nuse Doctrine\\ORM\\EntityManager;\n\nclass Doctrine\n{\n\u00a0\u00a0 \u00a0protected $entityManager;\n\u00a0\u00a0 \u00a0protected $container;\n\n\u00a0\u00a0\u00a0 public function __construct(EntityManager $entityManager, ContainerInterface $container)\n\u00a0\u00a0\u00a0 {\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$this-&amp;gt;container = $container;\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$this-&amp;gt;em = $entityManager;\n\u00a0\u00a0\u00a0 }\n\n\u00a0\u00a0\u00a0 public function getDoctrine()\n\u00a0\u00a0 \u00a0{\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$config = $this-&amp;gt;em-&amp;gt;getConfiguration();\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$config-&amp;gt;addCustomNumericFunction(&#039;INT&#039;, &#039;AN\\PruebaBundle\\Query\\CastAsInteger&#039;);\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0return $this-&amp;gt;em;\n\u00a0\u00a0 \u00a0}\n}<\/pre>\n<p>&nbsp;<\/p>\n<p>2) Agregamos este servicio a nuestro <strong>services.yml<\/strong><\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">#Creamos Servicio para instanciar Doctrine con config adicional\nan_doctrine:\n\u00a0\u00a0 \u00a0class:\u00a0\u00a0\u00a0\u00a0 &amp;quot;%an_doctrine.class%&amp;quot;\n\u00a0\u00a0 \u00a0arguments: &#x5B;@doctrine.orm.entity_manager, &amp;quot;@service_container&amp;quot;]\n\n<\/pre>\n<p>&nbsp;<\/p>\n<p>3) Agregamos <strong>an_doctrine.class<\/strong> a nuestro <strong>parameters.yml<\/strong>, si no, puedes agregarlo directamente en el Paso 2<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">an_doctrine.class: AN\\PruebaBundle\\Services\\Doctrine<\/pre>\n<p>&nbsp;<\/p>\n<p>4) Lo llamamos en nuestro Controller<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\/\/Doctrine\n$em = $this-&amp;gt;get(&#039;an_doctrine&#039;)-&amp;gt;getDoctrine();\n\u00a0\u00a0\u00a0 \n\n$dql = &amp;quot;SELECT a, INT(a.folio) AS HIDDEN orderId\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0FROM ANWebBundle:AvisoPago a\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0ORDER BY orderId ASC&amp;quot;;\n\n$query = $em-&amp;gt;createQuery($dql);\n\n<\/pre>\n<p>Y listo, ya carga nuestra nueva funcion, asi si requerimos agregar otra funcion personalizada, la agregamos a nuestro<strong> Servicio Doctrine<\/strong> y este la cargara<\/p>\n<p>&nbsp;<\/p>\n<div style=\"background:#FCC;\">\n<p><strong>OBSERVACION<\/strong><\/p>\n<p>Me he dado cuenta que esta funci\u00f3n funciona perfectamente para valores enteros positivos, es decir, si tienes un string y este contiene un valor positivo, esta funcion realiza la conversion exitosamente, pero si el valor que posee es negativo, retorna un valor totalmente distinto, por lo cual NO se recomienda para estos ultimos, una solucion parche para esos casos podria ser esta:<\/p>\n<\/div>\n<p>&nbsp;<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">(a.folio + 0)<\/pre>\n<p>&nbsp;<\/p>\n<p>Saludos<\/p>\n","protected":false},"excerpt":{"rendered":"<p>El problema es el siguiente, teniendo un campo String en donde se guarda un campo numerico se requeria ordenar por este, al ser String se ordenaba de una manera \u00abincorrecta\u00bb, en cierto modo es correcto pero dado el contenido no era lo esperado por el Usuario. Lo mas logico seria dejar este campo como Entero [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,12],"tags":[25],"class_list":["post-208","post","type-post","status-publish","format-standard","hentry","category-doctrine","category-symfony2-2","tag-symfony2"],"_links":{"self":[{"href":"https:\/\/arielnavarrete.cl\/blog\/wp-json\/wp\/v2\/posts\/208","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/arielnavarrete.cl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/arielnavarrete.cl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/arielnavarrete.cl\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/arielnavarrete.cl\/blog\/wp-json\/wp\/v2\/comments?post=208"}],"version-history":[{"count":0,"href":"https:\/\/arielnavarrete.cl\/blog\/wp-json\/wp\/v2\/posts\/208\/revisions"}],"wp:attachment":[{"href":"https:\/\/arielnavarrete.cl\/blog\/wp-json\/wp\/v2\/media?parent=208"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/arielnavarrete.cl\/blog\/wp-json\/wp\/v2\/categories?post=208"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/arielnavarrete.cl\/blog\/wp-json\/wp\/v2\/tags?post=208"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}