Estas en: Home > registros

Entradas etiquetadas con registros

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: El modelo (II)

0

Cuando Symfony construye el modelo, crea una clase de objeto base para cada una de las tablas definidas en schema.yml. Cada una de estas clases contiene una serie de constructores y accesores por defecto en función de la definición de cada columna: los métodos new, getXXX() y setXXX() (donde XXX es el nombre del campo) permiten crear y obtener las propiedades de los objetos:

  1. <?php
  2.  
  3. $articulo = new Articulo();
  4. $articulo->setTitulo('Mi primer artículo');
  5. $articulo->setContenido('Este es mi primer artículo. \n Espero que te guste.');
  6.  
  7. $titulo = $articulo->getTitulo();
  8. $contenido = $articulo->getContenido();

 

Para establecer el valor de varios campos a la vez, se puede utilizar el método fromArray(), que también se genera para cada clase objeto:

  1. <?php
  2.  
  3. $articulo->fromArray(array(
  4. 'titulo' => 'Mi primer artículo',
  5. 'contenido' => 'Este es mi primer artículo. \n Espero que te guste.'
  6. ));
  1. <?php
  2.  
  3. // Relación de "muchos a uno"
  4. echo $comentario->getArticulo()->getTitulo();
  5. => Mi primer artículo
  6. echo $comentario->getArticulo()->getContenido();
  7. => Este es mi primer artículo.
  8. Espero que te guste.
  9.  
  10. // Relación "uno a muchos"
  11. $comentarios = $articulo->getComentarios();

La columna articulo_id de la tabla blog_comentario define implícitamente una clave externa a la tabla blog_articulo. Cada comentario está relacionado con un artículo y un artículo puede tener muchos comentarios. Las clases generadas contienen 5 métodos que traducen esta relación a la forma orientada a objetos, de la siguiente manera:

  • $comentario->getArticulo(): para obtener el objeto Articulo relacionado
  • $comentario->getArticuloId(): para obtener el ID del objeto Articulo relacionado
  • $comentario->setArticulo($articulo): para definir el objeto Articulo relacionado
  • $comentario->setArticuloId($id): para definir el objeto Articulo relacionado a partir de un ID
  • $articulo->getComentarios(): para obtener los objetos Comentario relacionados
  1. <?php
  2.  
  3. $comentario = new Comentario();
  4. $comentario->setAutor('Steve');
  5. $comentario->setContenido('¡Es el mejor artículo que he leído nunca!');
  6.  
  7. // Añadir este comentario al anterior objeto $articulo
  8. $comentario->setArticulo($articulo);
  9.  
  10. // Sintaxis alternativa
  11. // Solo es correcta cuando el objeto artículo ya
  12. // ha sido guardado anteriormente en la base de datos
  13. $comentario->setArticuloId($articulo->getId());

El método getArticulo() devuelve un objeto de tipo Articulo, que permite utilizar el método accesor getTitulo(). Se trata de una alternativa mucho mejor que realizar la unión de las tablas manualmente, ya que esto último necesitaría varias líneas de código (empezando con la llamada al método $comment->getArticuloId()).

La variable $comentarios contiene un array de objetos de tipo Comentario. Se puede mostrar el primer comentario mediante $comentarios[0] o se puede recorrer la colección entera mediante foreach ($comentarios as $comentario).

Al utilizar el constructor new se crea un nuevo objeto, pero no un registro en la tabla blog_articulo. Si se modifica el objeto, tampoco se reflejan esos cambios en la base de datos. Para guardar los datos en la base de datos, se debe invocar el método save() del objeto.

  1. <?php
  2.  
  3. $articulo->save();
  1. <?php
  2.  
  3. foreach ($articulo->getComentarios() as $comentario)
  4. {
  5. $comentario->delete();
  6. }

Si se conoce la clave primaria de un registro concreto, se puede utilizar el método retrieveByPk() de la clase peer para obtener el objeto relacionado.

  1. <?php
  2.  
  3. $articulo = ArticuloPeer::retrieveByPk(7);

En algunos casos, la clave primaria está formada por más de una columna. Es esos casos, el método retrieveByPK() permite indicar varios parámetros, uno para cada columna de la clave primaria.

También se pueden obtener varios objetos a la vez mediante sus claves primarias, invocando el método retrieveByPKs(), que espera como argumento un array de claves primarias.

 

Cuando se quiere obtener más de un registro, se debe utilizar el método doSelect() de la clase peer correspondiente a los objetos que se quieren obtener. Por ejemplo, para obtener objetos de la clase Articulo, se llama al método ArticuloPeer::doSelect().

El primer parámetro del método doSelect() es un objeto de la clase Criteria, que es una clase para definir consultas simples sin utilizar SQL, para conseguir la abstracción de base de datos.

Un objeto Criteria vacío devuelve todos los objetos de la clase.

  1. <?php
  2.  
  3. $c = new Criteria();
  4. $articulos = ArticuloPeer::doSelect($c);
  5.  
  6. // Genera la siguiente consulta SQL
  7. SELECT blog_articulo.ID, blog_articulo.TITLE, blog_articulo.CONTENIDO,
  8. blog_articulo.CREATED_AT
  9. FROM blog_articulo;

Para las selecciones más complejas de objetos, se necesitan equivalentes a las sentencias WHERE, ORDER BY, GROUP BY y demás de SQL. El objeto Criteria dispone de métodos y parámetros para indicar todas estas condiciones. Por ejemplo, para obtener todos los comentarios escritos por el usuario Steve y ordenados por fecha:

  1. <?php
  2.  
  3. $c = new Criteria();
  4. $c->add(ComentarioPeer::AUTOR, 'Steve');
  5. $c->addAscendingOrderByColumn(ComentarioPeer::CREATED_AT);
  6. $comentarios = ComentarioPeer::doSelect($c);
  7.  
  8. // Genera la siguiente consulta SQL
  9. SELECT blog_comentario.ARTICULO_ID, blog_comentario.AUTOR, blog_comentario.CONTENIDO,
  10. blog_comentario.CREATED_AT
  11. FROM blog_comentario
  12. WHERE blog_comentario.autor = 'Steve'
  13. ORDER BY blog_comentario.CREATED_AT ASC;

as constantes de clase que se pasan como parámetros a los métodos add() hacen referencia a los nombres de las propiedades. Su nombre se genera a partir del nombre de las columnas en mayúsculas. Por ejemplo, para indicar la columna contenido de la tabla blog_articulo, se utiliza la constante de clase llamada ArticuloPeer::CONTENIDO.

Otro ejemplo del uso de Criteria con condiciones múltiples. En el ejemplo se obtienen todos los comentarios del usuario Steve en los artículos que contienen la palabra enjoy y además, ordenados por fecha.

 

  1. <?php
  2.  
  3. $c = new Criteria();
  4. $c->add(ComentarioPeer::AUTOR, 'Steve');
  5. $c->addJoin(ComentarioPeer::ARTICULO_ID, ArticuloPeer::ID);
  6. $c->add(ArticuloPeer::CONTENIDO, '%enjoy%', Criteria::LIKE);
  7. $c->addAscendingOrderByColumn(ComentarioPeer::CREATED_AT);
  8. $comentarios = ComentarioPeer::doSelect($c);
  9.  
  10. // Genera la siguiente consulta SQL
  11. SELECT blog_comentario.ID, blog_comentario.ARTICULO_ID, blog_comentario.AUTOR,
  12. blog_comentario.CONTENIDO, blog_comentario.CREATED_AT
  13. FROM blog_comentario, blog_articulo
  14. WHERE blog_comentario.AUTOR = 'Steve'
  15. AND blog_articulo.CONTENIDO LIKE '%enjoy%'
  16. AND blog_comentario.ARTICULO_ID = blog_articulo.ID
  17. ORDER BY blog_comentario.CREATED_AT ASC

Además del método doSelect(), todas las clases peer tienen un método llamado doCount(), que simplemente cuenta el número de registros que satisfacen las condiciones pasadas como parámetro y devuelve ese número como un entero.

Las clases peer también incluyen métodos doDelete(), doInsert() y doUpdate() (todos ellos requieren como parámetro un objeto de tipo Criteria).

Por último, si solo se quiere obtener el primer objeto, se puede reemplazar el método doSelect() por doSelectOne(). Es muy útil cuando se sabe que las condiciones de Criteria solo van a devolver un resultado, y su ventaja es que el método devuelve directamente un objeto en vez de un array de objetos.

A veces, no es necesario obtener los objetos, sino que solo son necesarios algunos datos calculados por la base de datos. Por ejemplo, para obtener la fecha de creación de todos los artículos, no tiene sentido obtener todos los artículos y después recorrer el array de los resultados.

Para realizar consultas a la base de datos con PDO, es necesario realizar los siguientes pasos:

  • Obtener la conexión con la base de datos.
  • Construir la consulta.
  • Crear una sentencia con esa consulta.
  • Iterar el result set que devuelve la ejecución de la sentencia.
  1. <?php
  2.  
  3. conexion = Propel::getConnection();
  4. $consulta = 'SELECT MAX(%s) AS max FROM %s';
  5. $consulta = sprintf($consulta, ArticuloPeer::CREATED_AT, ArticuloPeer::TABLE_NAME);
  6. $sentencia = $conexion->prepare($consulta);
  7. $sentencia->execute();
  8. $resultset = $sentencia->fetch(PDO::FETCH_OBJ);
  9. $max = $resultset->max;

Normalmente, cuando una tabla tiene una columna llamada created_at, se utiliza para almacenar un timestamp de la fecha de creación del registro. La misma idea se aplica a las columnas updated_at, cuyo valor se debe actualizar cada vez que se actualiza el propio registro.

La buena noticia es que Symfony reconoce estos nombres de columna y se ocupa de actualizar su valor de forma automática. No es necesario establecer manualmente el valor de las columnas created_at y updated_at; se actualizan automáticamente. Lo mismo se aplica a las columnas llamadas created_on y updated_on.

  1. <?php
  2.  
  3. $comentario = new Comentario();
  4. $comentario->setAutor('Steve');
  5. $comentario->save();
  6.  
  7. // Muestra la fecha de creación
  8. echo $comentario->getCreatedAt();
  9. => [fecha de la operación INSERT de la base de datos]

Además, los getters de las columnas de fechas permiten indicar el formato de la fecha como argumento:

  1. <?php
  2.  
  3. echo $comentario->getCreatedAt('Y-m-d');

 

Ir arriba