ZendFramework: problemas de codificación de caractéres con la Base de datos.

Este es otro caso en que me pena el tema de las codificaciones de caracteres.

SIEMPRE que uno trabaje con Bases de datos, sobre todo en paises de habla no-inglesa, se esta expuesto al tremendo cacho (problema) de manipular datos con caracteres no-ascii, como por ejemplo las ñ-Ñ y diversas vocales acentuadas, tildes, apostrofes, cremillas, tongos y cuanta modificacion rara se le pueda hacer a una letra.

Hasta ahora, he trabajado TODO con codificación utf8 por ser más amplia en este sentido que las otras codificaciones corrientes (iso-8859-1*, latin1, …).

Motivo

Trabajando con Zend Form, note un extraño comportamiento. Cuando establecía manualmente un dato en un campo, si este venía acentuado, entonces al dibujar por la vista, aparecía en blanco.

Haciendo un var_dump( $dato ); descubrí que la cadena de texto venía con caracteres mal formados. Preguntando en Foros del Web y navegando, dí con una pista.

El método escape() de Zend_View provocaba que la cadena mal formada retornara en blanco. Seguramente si me pongo a mirar el código fuente de Zend_Form* llegaré a encontrar una llamada a ese método (no lo he hecho, pero por el efecto lo deduzco).

Además, buscando por este problema, tanto en listas de correo sobre ZF, como en la documentación de Mysql y además en otra respuesta a mi pregunta en el mismo foro, encontré que existen 2 consultas SQL (para MySQL) que arreglan el problema:

SET NAMES 'UTF8'
SET CHARACTER SET UTF8

Pero eso es específico a Mysql. La otra solución es manipular la configuración del servidor, cosa que no se puede hacer en un hosting.

Solución

La solución básica es ejecutar esa par de consultas SQL. Pero hay que ver globalmente el problema para saber donde, como y cuando hacerlo.

De partida, mi aplicación pretender ser no-dependiente del motor de base de datos.

Lo otro, es que intento mantener “limpio” el diseño del código, en el sentido de que cada cosa valla en el lugar que corresponde, dependiendo del patrón y/o paradigma adoptado.

Entonces, no es cosa de llegar y ponerlo en el index.php

Una solución podría ser extender la clase Zend_Db_Adaptar_PdoMysql y añadir la consulta. Pero esto añade un propósito específico a algo que pretende ser general.

Bajo el mismo sentido de llegar a una solución generalizada, se me ocurrió externalizar el charset de la consulta. Así que simplemente, añadí un dato más al config.ini

database.adapter          = pdo_mysql   ; php extension, or Object adapter (1)
database.charset          = utf8        ; (optional) Character Set 
database.params.host      = localhost   ; database host
database.params.username  = username    ; username to conect database
database.params.password  = password    ; password to conect database
database.params.dbname    = goniumdb   ; name of database
database.params.prefix    = rox_        ; table prefix
database.params.profiler  = "1"         ; Enable/disable profiler

Los Controller Plugins básicos de Gonium los diseñé con el propósito de configurar cosas específicas, asi que decidí por el momento, hacer ahí las consultas, PERO solo cuando el adapter ocupado sea alguno basado en mysql. Así que finalmente mi código quedo así:

$config = Zend_Registry::get('core_config');
$db = Zend_Registry::get('core_db');
$db->getConnection();

// Set charset
if( isset($config->database->charset) && $config->database->charset !== null )
{
    switch( $config->database->adapter )
    {
        case 'mysql':
        case 'mysqli':
        case 'pdo_mysql':
            $db->query('SET NAMES \''.strtoupper($config->database->charset).'\'');
            $db->query('SET CHARACTER SET '.strtoupper($config->database->charset));
        break;
    }
}

Todo eso en el plugin Database. Es cosa de gustos en donde ponerlo, yo lo hice en un plugin, también se puede poner directo en el bootstrap, o extendiendo Zend_Db*, o que se yo…

¿Y luego que?

Creo que me veré obligado a probar YA en otros motores de base de datos, haber como se comportan…

9 comentarios sobre “ZendFramework: problemas de codificación de caractéres con la Base de datos.”

  1. Gracias!!!
    Realmente esta información me fue MUY UTIL y funcionó perfectamente aplicando lo aquí explicado.

    MUCHAS GRACIAS

  2. Ehhhh!!! no aparece ni tu nombre para agradecerte!!!!

    lo mejor de todo, además de que funciona perfecto, es que has sabido buscar el lugar para colocarlo prolijamente. Y además…LO HAS EXPLICADO EXCELENTEMENTE. MUCHAS GRACIAS!!!! 😀 😀 :woot:

  3. Por lo que se ve a la gente le funciona, pero a mi, al ser novato, no se donde colocar la solucion que propones, ¿Donde esta o cual es el plugin Database?

    Gracias por adelantado.

  4. hola, realmente grdezco mucho tu trabajo, pero lamentablemente no eh logrado hacer funcionar el codigo.
    Actualmente estoy levantando de una base de datos todo el contenido para publicarlo con flash (utilizo zend framework amf) y la verdad es que no encuentro donde publicar este codigo, me podrias dar la otra mano. Gracias!

  5. Amigos, el “plugin database” no existe como parte formal de zend framework. Es una adaptación que hice yo al proceso de Bootstrap antes incluso que existieran las clases de Zend_Application.

    Por eso ocupe como recurso crear un plugin para Zend_Controller que llame “Database” donde cargo un archivo.ini con los parámetros de mi conexión y ejecuto una primera conexión.

    Seguramente ahora que hay mecanismos más formales dentro del framework para hacer el proceso de Boostraping, supongo que en algún lado de Zend_Application también se puede incorporar.

    La solución que planteo acá es simplemente ejecutar una sentencia SQL, la magia esta en hacerlo antes que cualquier otra consulta.

  6. Gracias!
    En mi caso el problema eran los options de mis select, que aparecían directamente en blanco. Usé la pista de lo que publicaste y modifiqué el archivo “configs/application.ini”, agregando esta línea:

    resources.db.params.charset= utf8

    Quedó perfecto, muchas gracias por compartir!

  7. No se cuanto tiempo tenga este post, sin embargo dejo mi problema y la solución que encontré.

    Problema: Llenar un combo desde base de datos en formulario de Zend_Form y al hacerlo no me reconocía los valores con algún acento o la ñ.

    Solución: utf8_encode($valor); (solución aportada por richardinj en otro foro q no recuerdo cual es)

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Conoce cómo se procesan los datos de tus comentarios.