Una de las principales tareas a la hora de realizar un desarrollo o aplicación web , es la permanencia de los datos, Symfony incluye la librería Doctrine, que proporciona herramientas para simplificar el acceso y manejo de la información de la base de datos. Por esta razón me propuse a escribir este artículo, donde quiero que aprendas la filosofía de trabajo de Doctrine y lo fácil que puede ser trabajar con bases de datos.¿Interesado(a)? ¡Sigue leyendo!
Ahora bien, antes de comenzar, ten en cuenta que para seguir este tutorial ya debes contar con un Bundle o paquete dentro de tu aplicación, si no sabes cómo, revisa el artículo Crear Bundles en Symfony 2.
Es importante destacar que Doctrine no guarda ninguna relación con Symfony y su uso es totalmente opcional, por lo que adentrado más en Symfony si conoces algún otro ORM (Object Relational Mapper o Mapeo Objeto Relacional) puedes sentir libertad de usarlo.
En esta artículo te enseñare a configurar el acceso a la base de datos, a crear un objeto llamado Producto, para persistir su información en la base de datos y obtenerlo de nuevo mediante una consulta.

Comencemos

1.- Configurando la base de datos

Es necesario configurar la base de datos. Por convención, esta información se configura en el archivo app/config/parameters.yml:

En este momento Doctrine ya conoce nuestra base de datos, solo falta crearla con el siguiente comando:

Uno de los errores más habituales que cometen incluso los programadores más experimentados consiste en no configurar correctamente la codificación de caracteres de la base de datos.
En ocasiones, el problema es que lo configuran bien la primera vez, pero no cada vez que se crea de nuevo la base de datos. Esto sucede mucho cuando se desarrolla la aplicación, ya que es habitual emplear los siguientes comandos para borrar la base de datos y regenerarla con nueva información:

Doctrine no permite configurar estos valores por defecto en su archivo de configuración, ya que trata de ser lo más agnóstico posible en lo que se refiere a la configuración del entorno de ejecución.
Así que la solución más sencilla consiste en establecer estos valores por defecto en la propia configuración del servidor de base de datos. Si utilizas MySQL, añade las dos siguientes líneas en su archivo de configuración, que normalmente es my.cnf:

2.- Creando la entidad

Imagina que estás desarrollando una aplicación en la que vas a mostrar productos. Olvidándote de Doctrine y de las bases de datos, seguramente estás pensando en utilizar un objeto Producto para representar a los productos. Crea esta clase dentro del directorio Entity del bundle PonceelrelajadoDemoBundle:

Esta clase normalmente se llama “entidad” o “entity”, lo que significa que es una clase muy sencilla que sólo se utiliza para almacenar datos. Aunque se trata de una clase muy básica, cumple su objetivo de representar a los productos de tu aplicación. No obstante, esta clase no se puede guardar en una base de datos — es sólo una clase PHP simple.
Una vez aprendidos los conceptos fundamentales de Doctrine, podrás generar las clases de tipo entidad más fácilmente con el siguiente comando. Una vez ejecutado, Doctrine te hará varias preguntas para generar la entidad de forma interactiva:

3.- Añadir información de mapeo

Imagina que estás desarrollando una aplicación en la que vas a mostrar productos. Olvidándote de Doctrine y de las bases de datos, seguramente estás pensando en utilizar un objeto Producto para representar a los productos. Crea esta clase dentro del directorio Entity del bundle PonceelrelajadoDemoBundle:
Trabajar con Doctrine es mucho más interesante que hacerlo directamente con la base de datos. En vez de trabajar con filas y tablas, Doctrine te permite guardar y obtener objetos enteros a partir de la información de la base de datos. El truco para que esto funcione consiste en mapear una clase PHP a una tabla de la base de datos y después, mapear las propiedades de la clase PHP a las columnas de esa tabla, de manera que sólo tienes que añadir algunos metadatos a la clase PHP para configurar cómo se mapean la clase Producto y sus propiedades.

4.- Generando getters y setters

Doctrine ya sabe cómo persistir los objetos de tipo Producto en la base de datos, pero esa clase no es muy útil por el momento. Cómo Producto es una clase PHP normal y corriente, es necesario crear métodos getters y setters (getName(), setName(), etc.) para poder acceder a sus propiedades (porque son de tipo protected). Como esto es bastante habitual, existe un comando para que Doctrine añada estos métodos automáticamente:

Este comando asegura que la clase Product contiene todos los getters y setters necesarios. Puedes ejecutar de forma segura este comando una y otra vez, ya que los getters y setters sólo se generan si no existen (no se borran los métodos existentes).
Es importante destacar que los getters y setters generados por Doctrine son muy básicos, por lo dependiendo de la complejidad de tu aplicación, tendrás que ajustar el código a tus necesidades.
Utilizando el comando doctrine:generate:entities puedes:

  1. generar getters y setters;
  2. generar las clases de tipo Repository configuradas con la anotación @ORM\Entity(repositoryClass=”…”);
  3. generar el constructor adecuado para relaciones 1:n (uno a muchos) y n:m (muchos a muchos).

Para evitar problemas, el comando doctrine:generate:entities guarda una copia de seguridad del archivo Producto.php original en el archivo Producto.php~ (la diferencia está en el carácter ~ al final del nombre). En ocasiones esta copia de seguridad puede provocar en la aplicación errores de tipo “Cannot redeclare class”. Si se producen esos errores, puedes borrar este archivo sin problemas. También puedes añadir la opción –no-backup al comando anterior para no generar estas copias de seguridad.
También puedes generar a la vez todas las entidades de un bundle (es decir, cualquier clase PHP con información de mapeo de Doctrine) o de un espacio de nombres:

5.- Crear tabla en la base de datos

Aunque tienes una clase Product utilizable con información de mapeo para que Doctrine sepa persistirla, todavía no tienes su correspondiente tabla producto en la base de datos. Afortunadamente, Doctrine puede crear automáticamente todas las tablas necesarias en la base de datos (una para cada entidad conocida de tu aplicación). Para ello, ejecuta el siguiente comando:

En realidad, este comando es muy poderoso. Internamente compara la estructura que debería tener tu base de datos (según la información de mapeo de tus entidades) con la estructura que realmente tiene y genera las sentencias SQL necesarias para actualizar la estructura de la base de datos.
En otras palabras, si añades una nueva propiedad a la clase Producto y ejecutas este comando otra vez, se genera una sentencia de tipo ALTER TABLE para añadir la nueva columna a la tabla producto existente.
Una vez hayas ejecutado este comando, la base de datos cuenta ahora con una tabla llamada producto completamente funcional, y sus columnas coinciden con los metadatos que has especificado en la clase Producto.php.

6.- Persistiendo objetos en la base de datos

Ahora que tienes mapeada una entidad Producto y su tabla producto correspondiente, ya puedes persistir la información en la base de datos. De hecho, persistir información dentro de un controlador es bastante sencillo. Añade el siguiente método al controlador DefaultController del bundle:

No olvides crear una ruta que apunte a esta acción para poder probarla en el navegador, tal como se explica en el punto 2 del artículo Crear Bundles en Symfony, agrega estas lineas al final del archivo routing.yml de tu bundle:

Relacionado:  Cómo hacer un downgrade WordPress