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:

[codesyntax lang=»php» title=»Métodos generados en una clase objeto»]

<?php

$articulo = new Articulo();
$articulo->setTitulo('Mi primer artículo');
$articulo->setContenido('Este es mi primer artículo. \n Espero que te guste.');

$titulo    = $articulo->getTitulo();
$contenido = $articulo->getContenido();

[/codesyntax]

 

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:

[codesyntax lang=»php» title=»El método fromArray() es un setter múltiple»]

<?php

$articulo->fromArray(array(
  'titulo'   => 'Mi primer artículo',
  'contenido' => 'Este es mi primer artículo. \n Espero que te guste.'
));

[/codesyntax]

[codesyntax lang=»php» title=»Las claves externas se traducen en getters especiales»]

<?php

// Relación de "muchos a uno"
echo $comentario->getArticulo()->getTitulo();
 => Mi primer artículo
echo $comentario->getArticulo()->getContenido();
 => Este es mi primer artículo.
    Espero que te guste.

// Relación "uno a muchos"
$comentarios = $articulo->getComentarios();

[/codesyntax]

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

[codesyntax lang=»php» title=»Las claves externas se traducen en un setter especial»]

<?php

$comentario = new Comentario();
$comentario->setAutor('Steve');
$comentario->setContenido('¡Es el mejor artículo que he leído nunca!');

// Añadir este comentario al anterior objeto $articulo
$comentario->setArticulo($articulo);

// Sintaxis alternativa
// Solo es correcta cuando el objeto artículo ya
// ha sido guardado anteriormente en la base de datos
$comentario->setArticuloId($articulo->getId());

[/codesyntax]

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.

[codesyntax lang=»php»]

<?php

$articulo->save();

[/codesyntax]

[codesyntax lang=»php» title=»Borrar registros de la base de datos mediante el método delete() del objeto relacionado»]

<?php

foreach ($articulo->getComentarios() as $comentario)
{
  $comentario->delete();
}

[/codesyntax]

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.

[codesyntax lang=»php»]

<?php

$articulo = ArticuloPeer::retrieveByPk(7);

[/codesyntax]

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.

[codesyntax lang=»php» title=»Obtener registros mediante Criteria con el método doSelect() (Criteria vacío)»]

<?php

$c = new Criteria();
$articulos = ArticuloPeer::doSelect($c);

// Genera la siguiente consulta SQL
SELECT blog_articulo.ID, blog_articulo.TITLE, blog_articulo.CONTENIDO,
       blog_articulo.CREATED_AT
FROM   blog_articulo;

[/codesyntax]

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:

[codesyntax lang=»php» title=»Obtener registros mediante Criteria con el método doSelect() (Criteria con condiciones)»]

<?php

$c = new Criteria();
$c->add(ComentarioPeer::AUTOR, 'Steve');
$c->addAscendingOrderByColumn(ComentarioPeer::CREATED_AT);
$comentarios = ComentarioPeer::doSelect($c);

// Genera la siguiente consulta SQL
SELECT blog_comentario.ARTICULO_ID, blog_comentario.AUTOR, blog_comentario.CONTENIDO,
       blog_comentario.CREATED_AT
FROM   blog_comentario
WHERE  blog_comentario.autor = 'Steve'
ORDER BY blog_comentario.CREATED_AT ASC;

[/codesyntax]

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.

 

[codesyntax lang=»php»]

<?php

$c = new Criteria();
$c->add(ComentarioPeer::AUTOR, 'Steve');
$c->addJoin(ComentarioPeer::ARTICULO_ID, ArticuloPeer::ID);
$c->add(ArticuloPeer::CONTENIDO, '%enjoy%', Criteria::LIKE);
$c->addAscendingOrderByColumn(ComentarioPeer::CREATED_AT);
$comentarios = ComentarioPeer::doSelect($c);

// Genera la siguiente consulta SQL
SELECT blog_comentario.ID, blog_comentario.ARTICULO_ID, blog_comentario.AUTOR,
       blog_comentario.CONTENIDO, blog_comentario.CREATED_AT
FROM   blog_comentario, blog_articulo
WHERE  blog_comentario.AUTOR = 'Steve'
       AND blog_articulo.CONTENIDO LIKE '%enjoy%'
       AND blog_comentario.ARTICULO_ID = blog_articulo.ID
ORDER BY blog_comentario.CREATED_AT ASC

[/codesyntax]

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.

[codesyntax lang=»php» title=»Consultas SQL personalizadas con PDO»]

<?php

conexion = Propel::getConnection();
$consulta = 'SELECT MAX(%s) AS max FROM %s';
$consulta = sprintf($consulta, ArticuloPeer::CREATED_AT, ArticuloPeer::TABLE_NAME);
$sentencia = $conexion->prepare($consulta);
$sentencia->execute();
$resultset = $sentencia->fetch(PDO::FETCH_OBJ);
$max = $resultset->max;

[/codesyntax]

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.
[codesyntax lang=»php» title=»Las columnas created_at y updated_at se gestionan automáticamente»]

<?php

$comentario = new Comentario();
$comentario->setAutor('Steve');
$comentario->save();

// Muestra la fecha de creación
echo $comentario->getCreatedAt();
 => [fecha de la operación INSERT de la base de datos]

[/codesyntax]

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

[codesyntax lang=»php»]

<?php

echo $comentario->getCreatedAt('Y-m-d');

[/codesyntax]