Estas en: Home > utf8

Entradas etiquetadas con utf8

Logo Cassandra

Cassandra 1.x y PHP para desarrolladores SQL: phpCassa (III)

4

Ya he tratado casi en su totalidad las funciones más básicas de PHPCassa y Cassandra, con lo que ya tendrás un conocimiento suficientemente amplio de lo que se puede hacer con ellos, el resto dependerá de la evolución de la BD y de las librerías (y de la experiencia que tengas xP).

Hoy trataré varios temas que por las consultas realizadas por varios usuarios se merece un post aparte en el que se pueda tratar de una forma más amplia. Estos temas son: ordenar registros, crear keys para los registros y contar registros.

 

ORDENAR REGISTROS

Cassandra dispone de varios tipos de comparadores y subcomparadores para ordenar los registros. El más habitual es UTF-8 pero hay varios más. Si vamos a Cassandra Cluster Admin y accedemos al formulario de creación de columns family, podremos pasar el ratón por los interrogantes que hay a la izquierda de los campos para poder ver los diferentes tipos de comparadores:

Tipos de comparadores

Tipos de comparadores

Como puedes ver, estos comparadores le dicen a Cassandra como ordenar los registros. Si has seguido este tutorial ya conocerás al menos uno de los comparadores (utf-8) por tanto vamos a ver como ordena Cassandra los registros con este comparador.

Para este primer ejemplo vamos a crear una column family llamada column_family_order_utf8 de tipo standard y el tipo de comparador UTF8Type.

Vamos a nuestro archivo test.php y escribimos el siguiente código:

  1. <?php
  2.  
  3. $data = array();
  4. $data[5] = array(
  5. 'title' => 'Apache Cassandra',
  6. 'license' => 'Open Source',
  7. 'category' => 'no-sql',
  8. );
  9. $data[3] = array(
  10. 'title' => 'MongoDB',
  11. 'license' => 'Open Source',
  12. 'category' => 'no-sql'
  13. );
  14. $data[1] = array(
  15. 'title' => 'Neo4j',
  16. 'license' => 'Open Source',
  17. 'category' => 'no-sql',
  18. );
  19. $data[4] = array(
  20. 'title' => 'MySQL',
  21. 'license' => 'Open Source',
  22. 'category' => 'sql'
  23. );
  24. $data[2] = array(
  25. 'title' => 'MariaDB',
  26. 'license' => 'Open Source',
  27. 'category' => 'sql',
  28. );
  29.  
  30. foreach($data as $key => $value){
  31. $cass->guardar('column_family_order_utf8', $key, $value);
  32. }

Este código guardará un array desordenado en nuestra column family. Una vez ejecutado el script accedemos a Cassandra Cluster Admin y visualizamos los registros de column_family_order_utf8, nos mostrará el siguiente resultado:

Listado de los registros guardados

Listado de los registros guardados

Como puedes observar los registros no se han ordenado, sin embargo cada una de las columns de cada registro sí están ordenadas por orden alfabético. Esto sucede porque los comparadores no ordenan por keys o claves de los registros sino por columns, aunque hay un caso especial, si la column family es super los registros si estarán ordenados. Veamoslo.

Creamos una column family llamada column_family_utf8_super con el tipo de comparador UTF8Type y el tipo de column family como super. En nuestro archivo test.php añadimos el siguiente código:

  1. <?php
  2.  
  3. $data = array();
  4. $data[5] = array(
  5. 'title' => 'Apache Cassandra',
  6. 'license' => 'Open Source',
  7. 'category' => 'no-sql',
  8. );
  9. $data[3] = array(
  10. 'title' => 'MongoDB',
  11. 'license' => 'Open Source',
  12. 'category' => 'no-sql'
  13. );
  14. $data[1] = array(
  15. 'title' => 'Neo4j',
  16. 'license' => 'Open Source',
  17. 'category' => 'no-sql',
  18. );
  19. $data[4] = array(
  20. 'title' => 'MySQL',
  21. 'license' => 'Open Source',
  22. 'category' => 'sql'
  23. );
  24. $data[2] = array(
  25. 'title' => 'MariaDB',
  26. 'license' => 'Open Source',
  27. 'category' => 'sql',
  28. );
  29.  
  30. $cass->guardar('column_family_order_utf8_super', 'databases', $data);

Una vez ejecutado este script nos vamos a nuestra column family y nos mostrará lo siguiente:

Listado de registros en la column family

Listado de registros en la column family

Como puedes observar ahora sí están ordenados los registros, pero claro ahora están dentro de una super column.

En Cassandra la ordenación se realiza a las columnas del registro o los registros dentro de las super columns, si creasemos otra super column, esta no se ordenaría con respecto a la ya creada, ‘databases’.

Aunque esta ordenación puede ser útil y totalmente funcional, para los desarrolladores que vengan de las bases de datos relacionales les puede resultar confuso. Por ejemplo, para guardar los comentarios de un post de un blog podríamos utilizar este tipo de ordenación perfectamente, ya que podemos utilizar el id del post como key de la super column (el ‘databases’ de la imagen anterior se sustituiría por el id del post) y el timestamp (como este 1337787675.32246500) para la key de los registros. De esta forma tendríamos ordenados los comentarios por tiempo y por post. Si quisieramos recuperar los comentarios de un post concreto solo tendríamos que pasarle al método correspondiente el id del post como key de la super column.

¿Y si quisieramos guardar los post del blog? En este caso una column family super nos lo podría resolver indicando como key de la super columnposts‘  y utilizando como key en los registros el timestamp. Pero si quisieramos hacer busquedas utilizando indices secundarios una column family super no nos valdría, ya que los indices secundarios no funcionan en ellas.

Para ello habría que crear una column family standard para los post, que nos permitirá usar los indices secundarios, y una column family super para guardar las keys de los post dentro de una super column con key, por ejemplo, ‘key_posts‘. Para hacer la consulta habría que recuperar las keys de los posts a mostrar en primer lugar, y después, utilizando un método de PHPCassa que aun no hemos usado recuperar los registros correspondientes a esas keys.

El método que deberíamos añadir a nuestro archivo cassandra.php sería el siguiente:

 

  1. <?php
  2.  
  3. function obtenerMultiplesRegistros($name_columnFamily, $multiKeys, $super_column = ''){
  4.  
  5. if (!empty($super_column)){
  6. $column_family = new SuperColumnFamily($this->conexion, $name_columnFamily);
  7. $result = $column_family->multiget_super_column($multiKeys, $super_column);
  8. }
  9. else{
  10. $column_family = new ColumnFamily($this->conexion, $name_columnFamily);
  11. $result = $column_family->multiget($multiKeys);
  12. }
  13.  
  14. return $result;
  15.  
  16. }

 

A este método le pasamos el nombre de la column family standard donde hemos guardado los posts y un array con las keys a recuperar, nos devolverá un array con los datos de cada uno de los posts que le hemos pedido… y en el orden en el que le hayamos pasado las keys a recuperar.

Existe otra forma de ordenar registros, pero además de que en versiones posteriores de Cassandra desaparecerá y provoca problemas de rendimiento, yo no la recomiendo, ya que pierdes todos los beneficios que ofrece Cassandra. Aun así os dejo un link para que le echéis un ojo xD:

http://ria101.wordpress.com/2010/02/22/cassandra-randompartitioner-vs-orderpreservingpartitioner/

Y os dejo otro link para que tengais algo más de información respecto a ordenar registros en Cassandra:

http://ayogo.com/blog/2010/04/09/sorting-in-cassandra/

 

CREAR CLAVES O KEYS PARA LOS REGISTROS

Como has podido ver en el apartado anterior, para ordenar los registros es muy importante tener una key de cada registro que sea única y siempre vaya en orden. Esto las bases de datos relacionales nos lo dan ya hecho, sin embargo en las bases de datos no-sql esto no es así.

Las bases de datos no-sql se crearon para optimizar la lectura y escritura de los registros en la base de datos, esto provocó que algunas funcionalidades muy útiles en las bases relaciones no tuvieran cabida en las no-sql. Por tanto para mantener en orden los registros debemos crear nosotros nuestras propias claves.

PHPCassa dispone de un método para crear una clave aleatoria basada en el timestamp.

Para utilizarla primero añadiremos la clase a nuestra lista:

  1. <?php
  2.  
  3. use phpcassa\Connection\ConnectionPool;
  4. use phpcassa\ColumnFamily;
  5. use phpcassa\SuperColumnFamily;
  6. use phpcassa\ColumnSlice;
  7. use phpcassa\SystemManager;
  8. use phpcassa\Schema\StrategyClass;
  9. use phpcassa\Index\IndexExpression;
  10. use phpcassa\Index\IndexClause;
  11. use phpcassa\UUID;

Ahora crearemos un nuevo método en nuestro archivo cassamdra.php que devolverá la clave:

 

  1. <?php
  2.  
  3. public function obtenerUuid(){
  4.  
  5. $util = new UUID;
  6.  
  7. return $util->import($util->uuid1());
  8. }

 

Como me está quedando un post muy largo os voy a dejar algo de deberes xD. Sería interesante probarlo tanto con column families standard y super, además de con un tipo de comparador UTF8Type y TimeUUIDType.

Como el chorro de letras y números que devuelve es muy poco legible yo suelo utilizar mi propio sistema de claves, normalmente utilizo el microtime() de php y un par de ids de lo que se esté guardando: el id del usuario, el id de lo que se ha creado, etc. Algo que lo diferencie del resto. Para la clave primero pongo los segundos que devuelve microtime() y después los microsegundos. Para que os hagais una idea sería algo así:

$key = $segundos . ‘.’ . $microsegundos . ‘_’ . $id_post . ‘_’ . $id_usuario;

De esta forma le estamos dando una clave para los ejemplos del anterior apartado, más concretamente para los comentarios en un post.

 

CONTAR REGISTROS

El último apartado de este post. Contar registros. Esto es algo que Cassandra no lleva muy bien, sobre todo con grandes cantidades de información.

Cassandra cuando recibe una petición de lectura/escritura utiliza unas tablas en memoria llamadas memtables (el que le puso el nombre de rompió la cabeza pensando). Cuantas más peticiones reciba Cassandra más memtables creará, de esta forma permitirá una cierta consistencia de la información almacenada en la base de datos.

Cuando le pedimos a phpCassa que nos devuelva el número de registros en una column family o en una super column concreta, lo que está haciendo en realidad es hacer una petición a Cassandra de todos los registros que haya en la column family o en la super column. Cuando esto ocurre Cassandra guardará estos registros en la RAM del servidor antes de enviarlos a phpCassa, y sí Cassandra no cuenta los registros, porque no está pensada para eso, es phpCassa la que cuenta los registros y te devuelve el número concreto.

El método que utiliza phpCassa para contar registros es el que os muestro a continuación, dentro de un método para añadir al archivo cassandra.php:

 

  1. <?php
  2.  
  3. public function contar_registros($name_columnFamily, $key, $super_column='', $range_start='', $range_end=''){
  4.  
  5. $column_slice = new ColumnSlice($range_start, $range_end);
  6.  
  7. if (!empty($super_column)){
  8. $column_family = new SuperColumnFamily($this->conexion, $name_columnFamily);
  9. $result = $column_family->get_subcolumn_count($key, $super_column, $column_slice);
  10. }
  11. else{
  12. $column_family = new ColumnFamily($this->conexion, $name_columnFamily);
  13. $result = $column_family->get_count($key, $column_slice);
  14. }
  15.  
  16. return $result;
  17.  
  18. }

 

Esta forma de contar registros provoca que Cassandra consuma todos los recursos de RAM del servidor, con lo que no os la recomiendo.

La mejor manera de contar registros con Cassandra es utilizar una column family con contadores, de tal forma que en nuestro código cada vez que se guarde un registro en la bd se aumente el contador que lleva la cuenta de los registros guardados. En el caso de que se eliminen, habría que disminuirlo. Y en el caso de que el registro se esté actualizando controlar que no aumente el contador xD.

Cualquier duda que tengais intentaré responderla lo mejor posible en los comentarios.

Logo Cassandra

Cassandra y PHP para desarrolladores SQL: phpCassa (III)

0

Ya he tratado casi en su totalidad las funciones más básicas de phpCassa y Cassandra, con lo que ya tendrás un conocimiento suficientemente amplio de lo que se puede hacer con phpCassa y Cassandra, el resto dependerá de la evolución de la BD y de las librerías (y de la experiencia que tengas xP).

Hoy trataré varios temas que por las consultas realizadas por varios usuarios se merece un post aparte en el que se pueda tratar de una forma más amplia. Estos temas son: ordenar registros, crear keys para los registros y contar registros.

 

ORDENAR REGISTROS

Cassandra dispone de varios tipos de comparadores y subcomparadores para ordenar los registros. El más habitual es UTF-8 pero hay varios más. Si vamos a Cassandra Cluster Admin y accedemos al formulario de creación de columns family, podremos pasar el ratón por los interrogantes que hay a la izquierda de los campos para poder ver los diferentes tipos de comparadores:

Tipos de comparadores

Tipos de comparadores

Como puedes ver, estos comparadores le dicen a Cassandra como ordenar los registros. Si has seguido este tutorial ya conocerás al menos uno de los comparadores (utf-8) por tanto vamos a ver como ordena Cassandra los registros con este comparador.

Para este primer ejemplo vamos a crear una column family llamada column_family_order_utf8 de tipo standard y el tipo de comparador UTF8Type.

Vamos a nuestro archivo test.php y escribimos el siguiente código:

  1. <?php
  2.  
  3. $data = array();
  4. $data[5] = array(
  5. 'title' => 'Apache Cassandra',
  6. 'license' => 'Open Source',
  7. 'category' => 'no-sql',
  8. );
  9. $data[3] = array(
  10. 'title' => 'MongoDB',
  11. 'license' => 'Open Source',
  12. 'category' => 'no-sql'
  13. );
  14. $data[1] = array(
  15. 'title' => 'Neo4j',
  16. 'license' => 'Open Source',
  17. 'category' => 'no-sql',
  18. );
  19. $data[4] = array(
  20. 'title' => 'MySQL',
  21. 'license' => 'Open Source',
  22. 'category' => 'sql'
  23. );
  24. $data[2] = array(
  25. 'title' => 'MariaDB',
  26. 'license' => 'Open Source',
  27. 'category' => 'sql',
  28. );
  29.  
  30. foreach($data as $key => $value){
  31. $cass->guardar('column_family_order_utf8', $key, $value);
  32. }

Este código guardará un array desordenado en nuestra column family. Una vez ejecutado el script accedemos a Cassandra Cluster Admin y visualizamos los registros de column_family_order_utf8, nos mostrará el siguiente resultado:

Listado de los registros guardados

Listado de los registros guardados

Como puedes observar los registros no se han ordenado, sin embargo cada una de las columns de cada registro sí están ordenadas por orden alfabético. Esto sucede porque los comparadores no ordenan por keys o claves de los registros sino por columns, aunque hay un caso especial, si la column family es super los registros si estarán ordenados. Veamoslo.

Creamos una column family llamada column_family_utf8_super con el tipo de comparador UTF8Type y el tipo de column family como super. En nuestro archivo test.php añadimos el siguiente código:

  1. <?php
  2.  
  3. $data = array();
  4. $data[5] = array(
  5. 'title' => 'Apache Cassandra',
  6. 'license' => 'Open Source',
  7. 'category' => 'no-sql',
  8. );
  9. $data[3] = array(
  10. 'title' => 'MongoDB',
  11. 'license' => 'Open Source',
  12. 'category' => 'no-sql'
  13. );
  14. $data[1] = array(
  15. 'title' => 'Neo4j',
  16. 'license' => 'Open Source',
  17. 'category' => 'no-sql',
  18. );
  19. $data[4] = array(
  20. 'title' => 'MySQL',
  21. 'license' => 'Open Source',
  22. 'category' => 'sql'
  23. );
  24. $data[2] = array(
  25. 'title' => 'MariaDB',
  26. 'license' => 'Open Source',
  27. 'category' => 'sql',
  28. );
  29.  
  30. $cass->guardar('column_family_order_utf8_super', 'databases', $data);

Una vez ejecutado este script nos vamos a nuestra column family y nos mostrará lo siguiente:

Listado de registros en la column family

Listado de registros en la column family

Como puedes observar ahora sí están ordenados los registros, pero claro ahora están dentro de una super column.

En Cassandra la ordenación se realiza a las columnas del registro o los registros dentro de las super columns, si creasemos otra super column, esta no se ordenaría con respecto a la ya creada, ‘databases’.

Aunque esta ordenación puede ser útil y totalmente funcional, para los desarrolladores que vengan de las bases de datos relacionales les puede resultar confuso. Por ejemplo, para guardar los comentarios de un post de un blog podríamos utilizar este tipo de ordenación perfectamente, ya que podemos utilizar el id del post como key de la super column (el ‘databases’ de la imagen anterior se sustituiría por el id del post) y el timestamp (como este 1337787675.32246500) para la key de los registros. De esta forma tendríamos ordenados los comentarios por tiempo y por post. Si quisieramos recuperar los comentarios de un post concreto solo tendríamos que pasarle al método correspondiente el id del post como key de la super column.

¿Y si quisieramos guardar los post del blog? En este caso una column family super nos lo podría resolver indicando como key de la super columnposts‘  y utilizando como key en los registros el timestamp. Pero si quisieramos hacer busquedas utilizando indices secundarios una column family super no nos valdría, ya que los indices secundarios no funcionan en ellas.

Para ello habría que crear una column family standard para los post, que nos permitirá usar los indices secundarios, y una column family super para guardar las keys de los post dentro de una super column con key, por ejemplo, ‘key_posts‘. Para hacer la consulta habría que recuperar las keys de los posts a mostrar en primer lugar, y después, utilizando un método de phpCassa que aun no hemos usado recuperar los registros correspondientes a esas keys.

El método que deberíamos añadir a nuestro archivo cassandra.php sería el siguiente:

  1. <?php
  2.  
  3. function obtenerMultiplesRegistros($columnFamily, $multiKeys){
  4.  
  5. $column_family = new ColumnFamily($this->conexion, $columnFamily);
  6.  
  7. $result = $column_family->multiget($multiKeys);
  8.  
  9. return $result;
  10.  
  11. }

A este método le pasamos el nombre de la column family standard donde hemos guardado los posts y un array con las keys a recuperar, nos devolverá un array con los datos de cada uno de los posts que le hemos pedido… y en el orden en el que le hayamos pasado las keys a recuperar.

Existe otra forma de ordenar registros, pero además de que en versiones posteriores de Cassandra desaparecerá y provoca problemas de rendimiento, yo no la recomiendo, ya que pierdes todos los beneficios que ofrece Cassandra. Aun así os dejo un link para que le echéis un ojo xD:

http://ria101.wordpress.com/2010/02/22/cassandra-randompartitioner-vs-orderpreservingpartitioner/

Y os dejo otro link para que tengais algo más de información respecto a ordenar registros en Cassandra:

http://ayogo.com/blog/2010/04/09/sorting-in-cassandra/

 

CREAR CLAVES O KEYS PARA LOS REGISTROS

Como has podido ver en el apartado anterior, para ordenar los registros es muy importante tener una key de cada registro que sea única y siempre vaya en orden. Esto las bases de datos relacionales nos lo dan ya hecho, sin embargo en las bases de datos no-sql esto no es así.

Las bases de datos no-sql se crearon para optimizar la lectura y escritura de los registros en la base de datos, esto provocó que algunas funcionalidades muy útiles en las bases relaciones no tuvieran cabida en las no-sql. Por tanto para mantener en orden los registros debemos crear nosotros nuestras propias claves.

phpCassa dispone de un método para crear una clave aleatoria basada en el timestamp, para utilizarla crearemos un nuevo método en nuestro archivo cassamdra.php que devolverá la clave:

  1. <?php
  2.  
  3. public function obtenerUuid(){
  4.  
  5. $util = new CassandraUtil();
  6.  
  7. return $util->import($util->uuid1());
  8. }

Como me está quedando un post muy largo os lo voy a dejar como deberes xD. Sería interesante probarlo tanto con column families standard y super, además de con un tipo de comparador UTF8Type y TimeUUIDType.

Como el chorro de letras y números que devuelve es muy poco legible yo suelo utilizar mi propio sistema de claves, normalmente utilizo el microtime() de php y un par de ids de lo que se esté guardando: el id del usuario, el id de lo que se ha creado, etc. Algo que lo diferencie del resto. Para la clave primero pongo los segundos que devuelve microtime() y después los microsegundos. Para que os hagais una idea sería algo así:

$key = $segundos . ‘.’ . $microsegundos . ‘_’ . $id_post . ‘_’ . $id_usuario;

De esta forma le estamos dando una clave para los ejemplos del anterior apartado, más concretamente para los comentarios en un post.

 

CONTAR REGISTROS

El último apartado de este post. Contar registros. Esto es algo que Cassandra no lleva muy bien, sobre todo con grandes cantidades de información.

Cassandra cuando recibe una petición de lectura/escritura utiliza unas tablas en memoria llamadas memtables (el que le puso el nombre de rompió la cabeza pensando). Cuantas más peticiones reciba Cassandra más memtables creará, de esta forma permitirá una cierta consistencia de la información almacenada en la base de datos.

Cuando le pedimos a phpCassa que nos devuelva el número de registros en una column family o en una super column concreta, lo que está haciendo en realidad es hacer una petición a Cassandra de todos los registros que haya en la column family o en la super column. Cuando esto ocurre Cassandra guardará estos registros en la RAM del servidor antes de enviarlos a phpCassa, y sí Cassandra no cuenta los registros, porque no está pensada para eso, es phpCassa la que cuenta los registros y te devuelve el número concreto.

El método que utiliza phpCassa para contar registros es el que os muestro a continuación, dentro de un método para añadir al archivo cassandra.php:

  1. <?php
  2.  
  3. public function contar_registros($columnFamily, $key){
  4.  
  5. $column_family = new ColumnFamily($this->conexion, $columnFamily);
  6.  
  7. return $column_family->get_count($key);
  8.  
  9. }

Esta forma de contar registros provoca que Cassandra consuma todos los recursos de RAM del servidor, con lo que no os la recomiendo.

La mejor manera de contar registros con Cassandra es utilizar una column family con contadores, de tal forma que en nuestro código cada vez que se guarde un registro en la bd se aumente el contador que lleva la cuenta de los registros guardados. En el caso de que se eliminen, habría que disminuirlo. Y en el caso de que el registro se esté actualizando controlar que no aumente el contador xD.

Cualquier duda que tengais intentaré responderla lo mejor posible en los comentarios.

#symfony, I18N, UTF-8 y Dreamweaver

0

Supongo que ya sabrás de lo que voy a hablar, sí, codificación de caracteres y el jodío de Dreamweaver. Te cuento:

Estoy haciendo algunas pruebas con Symfony y su sistema de internacionalización ( I18N ), y para ello he hecho que el charset que muestre la plantilla sea utf-8 (además de las tablas de la BD y las conexiones desde y hacía la BD), lo curioso es que cuando he ido a verlo en el navegador el resultado me aparecía con chinos (unos cuadrados (aunque pueden ser otros símbolos) que sustituyen a las letras con tilde), total que me he tirado todo el día dándole vueltas al tema, y el problema lo tenía en Dreamweaver que, por defecto, guarda los archivos en “Europeo occidental” y no en utf-8.

Te explico todo lo que he modificado en el proyecto de Symfony, por si te pasa algo parecido puedas comparar. Con esta configuración que te voy a mostrar el sistema de internacionalización de Symfony funciona al 100%:

Antes de nada te informo que esto está pensado para Symfony 1.4, versiones superiores o inferiores pueden necesitar una configuración distinta. Cuando hablo de Dreamweaver me refiero a la versión CS3, aunque muy probablemente algo parecido haya en versiones superiores.

settings.yml

Doy por hecho que ya has creado el proyecto, al menos una aplicación y un módulo con el que hacer pruebas. Nos vamos al archivo settings.yml de la app y añadimos:

 

  1. all:
  2. .settings:
  3.  
  4. # Indicamos la cultura por defecto
  5. # Aquí poned la que os interese
  6. default_culture: es_ES
  7.  
  8. # Indicamos la codificación de caracteres
  9. charset: utf-8
  10.  
  11. # Esto lo dejo a tu elección
  12. # Puedes escribir esta línea para que el helper I18N esté
  13. # en todas las plantillas de forma global
  14. # Lo bueno de usar esta opción es que puedes añadir
  15. # más helpers:
  16. # standard_helpers: [I18N,text, etc]
  17. standard_helpers: [I18N]
  18.  
  19. # O puedes escribir esta otra línea, pero
  20. # en cada una de las plantillas tendrás que incluir
  21. # al prinicipio <?php use_helper('I18N') ?>
  22. # la decisión es tuya
  23. i18n: true

 

routing.yml

Modificamos este archivo para indicar el módulo que se mostrará como página de inicio (homepage):

 

  1. # Esto es lo que está por defecto
  2. homepage:
  3. url: /
  4. param: { module: default, action: index }
  5.  
  6. # Lo único que cambio es el nombre del módulo, que en mi caso es 'login'
  7. homepage:
  8. url: /
  9. param: { module: login, action: index }

 

 

view.yml

Este archivo creo que no hacia falta modificarlo para la internacionalización, pero por si acaso:

  1. metas:
  2. language: es

 

indexSuccess.php del módulo

Añadimos el texto que vamos a probar:

  1. // No voy a poner todo el código que tengo en mi plantilla
  2. // así que pongo solo un ejemplo
  3.  
  4. <?php echo __('Hola Mundo!') ?>
  5.  
  6. // Esto te mostrará el texto en español

Bien, como le hemos dado el valor “es_ES” a “default_culture“, Symfony no mostrará ninguna traducción sino el valor que le hemos indicado en la plantilla. Para hacer una prueba en condiciones vamos a modificar la cultura de un usuario a “en_EN“, esto mantendrá la cultura de todo el proyecto como “es_ES“.

 

actions.class.php del módulo

En la acción Index escribimos lo siguiente:

  1. class loginActions extends sfActions
  2. {
  3. /**
  4. * Executes index action
  5. *
  6. * @param sfRequest $request A request object
  7. */
  8. public function executeIndex(sfWebRequest $request)
  9. {
  10.  
  11. // Esta línea cambiará la cultura SÓLO para el usuario
  12. $this -> getUser() -> setCulture('en_EN');
  13.  
  14. return sfView::SUCCESS;
  15. }
  16. }

Obviamente nos falta crear el archivo que le indicará a Symfony el texto que debe utilizar para su sustitución. A ello voy:

 

english.en.xml

Este archivo se guarda en la carpeta “i18n” de la app, aunque también puedes crear la carpeta dentro del módulo y guardar el archivo allí. Este archivo tiene un formato especial que se debe mantener:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <xliff version="1.0">
  3. <file orginal="global" source-language="en_EN" datatype="plaintext">
  4. <body>
  5. <trans-unit id="1">
  6. <source>Hola Mundo!</source>
  7. <target>Hello World!</target>
  8. </trans-unit>
  9. <trans-unit id="2">
  10. <source>soy un texto</source>
  11. <target>I'm a text</target>
  12. </trans-unit>
  13. <trans-unit id="3">
  14. <source>Adiós</source>
  15. <target>Bye</target>
  16. </trans-unit>
  17. </body>
  18. </file>
  19. </xliff>

Cosas importantes respecto de este archivo:

  • Le puedes poner cualquier nombre pero debe acabar en *.culture.xml, por ejemplo: login.en.xml, registro.en.xml, administracion.fr.xml, comentario.it.xml.
  • También se puede poner la cultura completa, es decir, en vez de solo *.en.xml puedes nombrarlo como *.en_EN.xml.
  • El parámetro “source-language” siempre debe indicar la cultura que se va a traducir, en este caso es el ingles (en_EN).
  • Cada texto a traducir está dentro de la etiqueta <trans-unit>, que tiene el atributo id, pues bien, cada frase a traducir debe aumentar el id ( 1,2,3,4,5….500 etc)
  • No es necesario que todas las frases estén en un solo archivo, puede haber varios archivos con textos diferentes, por ejemplo, para el menú, la cabecera, el pie de página, etc.,. Importante: aunque sean archivos para idiomas diferentes el nombre del archivo siempre debe ser el mismo, variando, eso sí, la cultura.

Una vez guardado el archivo volvemos al indexSuccess.php y lo modificamos para que quede tal que así;

  1. // No voy a poner todo el código que tengo en mi plantilla
  2. // así que pongo solo un ejemplo
  3.  
  4. <?php echo __('Hola Mundo!', null, 'login') ?>
  5.  
  6. // Ahora mostrará el texto que corresponda con la cultura del usuario
  7. // Además lo buscará en un archivo concreto en este caso login.en.xml

Y así se internacionaliza un proyecto Symfony. Ahora el problemita de Dreamweaver:

El bicho, (por llamarlo de alguna manera) tiene una opción para abrir archivos que no indiquen su codificación. Normalmente está en “Europeo occidental” y debería estar en “Unicode (utf-8)“. Para cambiarlo accedemos al menú “Edición -> Preferencias…” y en “Nuevo documento” busca un desplegable que ponga “Codificación pred.“; ahí elige “Unicode (utf-8)“, activa la casilla que dice “Utilizar al abarir archivos existentes que no indiquen su codificación” y en el desplegable de abajo (Formulario de normas Unicode) selecciona “C (descomposición de compatibilidad seguida de composición canónica)“. Pulsa aceptar y prueba el en navegador.

Tal vez tengas que limpiar la cache de Symfony para ello solo tienes que escribir en la consola (que debe apuntar a la carpeta donde tienes el proyecto) symfony cc o php symfony cc.

Si sigue fallando, abre el archivo indexSuccess.php del módulo con el bloc de notas, y sin modificar nada, vete a Archivo -> Guardar como… , ahí podrás elegir la codificación, en nuestro caso, utf-8, y para evitar que se guarde como un archivo .txt elige “Todos los archivos” y así se guardará en php. Vuelve a limpiar la caché y vuelve a probar, ahora sí te debería funcionar bien.

PHP: eregi_replace() y UTF-8 (Problema y solución)

0

Esto creando una nueva web, y como ya deberíais saber, los desarrolladores de PHP decidieron que la versión 6 funcionaría, por defecto, con el charset utf-8. Los que esteis ya implementando estos cambios en vuestros proyectos, conocereis los quebraderos de cabeza que dan tanto mySQL como PHP sino están bien configurados (uno de ellos lo comente hace un tiempo aquí).

Pues bien, hoy me he topado con otro, que me ha tenido todo el día dandome cabezazos contra la mesa, hasta que por fin he descubierto que leches pasaba.
Continue reading “PHP: eregi_replace() y UTF-8 (Problema y solución)” »

Ir arriba