[Parte 4] El modelo de comentarios: repositorios y migraciones de Doctrine

Symfony, Tutoriales

Este post es la parte 4 de 6 del artículo: Creando un Blog con Symfony2

Debido a que la web de udelabs lleva varías semanas sin funcionar a petición de un par de usuarios me tomo la libertad de subir el tutorial traducido por ellos, quizás con alguna modificación que iba haciendo pero todos los méritos son de ellos.Tutorial en inglés 

Descripción

En este capítulo construiremos sobre el modelo del blog que definimos en el capítulo anterior. Vamos a crear el modelo para los Comentarios, el cual cómo su nombre indica, se encargará de los comentarios de cada blog. Te presentaremos la creación de relaciones entre modelos, cómo puede un blog contener muchos Comentarios. Vamos a utilizar el Generador de consultas de Doctrine 2 y las clases Repositorio deDoctrine para recuperar entidades desde la base de datos. También exploraremos el concepto de Migraciones de Doctrine 2 que ofrece una forma programática para implementar cambios en la base de datos. Al final de este capítulo habrás creado el modelo del Comentario y lo habrás vinculado con el modelo del Blog. Además crearemos la página Inicial, y proporcionaremos la posibilidad de que los usuarios envíen comentarios para un blog.

La página Inicial

Vamos a comenzar este capítulo, construyendo la página inicial de la aplicación. Al estilo de un verdadero blogger mostraremos fragmentos de cada entrada del blog, ordenados del más reciente al más antiguo. La entrada completa del blog estará disponible a través de enlaces a la página que muestra el blog. Puesto que ya hemos construido la ruta, el controlador y la vista de la página, simplemente vamos a actualizarlas.

Recuperando los blogs: Consultando el modelo

Con el fin de mostrar los blogs, los tenemos que recuperar desde la base de datos. Doctrine 2 proporciona el Lenguaje de consulta Doctrine (DQL) y un Generador de consultas para lograr esto (también puedes ejecutar SQL crudo a través de Doctrine 2, pero este método no se recomienda, ya que quita la abstracción de bases de datos que nos brinda Doctrine 2). Vamos a utilizar el Generador de consultas, ya que nos proporciona una agradable forma orientada a objetos, para generar DQL, que puedes utilizar para consultar la base de datos. Actualicemos la acción index del controlador Page que se encuentra ensrc/Blogger/BlogBundle/Controller/PageController.php para recuperar los blogs de la base de datos.

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Controller/PageController.php”]

[/codesyntax]

Empezamos consiguiendo una instancia del QueryBuilder desde el EntityManager. Esto nos permite empezar a construir la consulta con los muchos métodos que ofrece el Generador de consultas. La lista completa de métodos disponibles está en la documentación del Generador de consultas. Un buen lugar para comenzar es con los métodos ayudantes. Estos son los métodos que usaremos, como select(),from() y addOrderBy(). Al igual que con las interacciones previas con Doctrine 2, podemos utilizar la notación abreviada para hacer referencia a la entidad Blog a través del BloggerBlogBundle:Blog (recuerda que esto hace lo mismo que BloggerBlogBundleEntityBlog). Cuando hayas terminado de especificar los criterios para la consulta, llamamos al método getQuery() el cual devuelve una instancia de DQL. No podremos obtener resultados desde el objeto QueryBuilder, siempre lo tenemos que convertir en una instancia de DQL primero. La instancia de DQL ofrece el método getResult() que devuelve una colección de entidades Blog. Más adelante veremos que la instancia del DQL tiene una serie de métodos para devolver su resultado, tal como getSingleResult() y getArrayResult().

La vista

Ahora tenemos una colección de entidades Blog y necesitamos mostrarlas. Sustituye el contenido de la plantilla de la página Inicial ubicada ensrc/Blogger/BlogBundle/Resources/views/Page/index.html.twig con lo siguiente:

[codesyntax lang=”html4strict” title=”src/Blogger/BlogBundle/Resources/views/Page/index.html.twig “]

[/codesyntax]

Aquí te presentamos una de las estructuras de control de Twig, la estructura for..else..endfor. Si no has utilizado un motor de plantillas antes,probablemente te sea familiar el siguiente fragmento de códigoPHP.

[codesyntax lang=”php”]

[/codesyntax]

La estructura de control for..else..endfor es una manera mucho más limpia de lograr esta tarea. La mayoría del código en la plantilla de la página Inicial atañe a la reproducción de la información del blog enHTML. Sin embargo, hay algunas cosas que es necesario tener en cuenta. En primer lugar, usamos la función path de Twig para generar las rutas de la página show del blog. Puesto que la página show del blogrequiere que esté presente un id de blog en la URL, lo tenemos que pasar como argumento de la función path. Esto se puede ver con lo siguiente:

[codesyntax lang=”html4strict”]

[/codesyntax]

En segundo lugar reproducimos el contenido del blog utilizando <p>{{ blog.blog(500) }}</p>. El argumento 500 que pasamos, es la longitud máxima de la entrada en el blog que queremos recibir de vuelta desde la función. Para que esto funcione tenemos que actualizar el método getBlog que Doctrine 2 generó anteriormente para nosotros. Actualiza el método getBlog en la entidad blog ubicada ensrc/Blogger/BlogBundle/Entity/Blog.php.

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Entity/Blog.php”]

[/codesyntax]

Debido a que el comportamiento habitual del método getBlog debe devolver la entrada completa en el blog, establecemos el parámetro $length para que tenga un valor predeterminado de null. Si se le pasa null, devuelve todo el blog.

Ahora bien, si apuntas tu navegador a http://symblog.dev/app_dev.php/ deberías ver la página Inicial exhibiendo las entradas más recientes del blog. También deberías poder navegar a la entrada completa delblog por cada entrada haciendo clic en el título del blog o en los enlaces ‘continuar leyendo…’.

Página de inicio del blog

A pesar de que puedes consultar por entidades en el controlador, ese no es el mejor lugar para hacerlo. La consulta estará en mejores condiciones fuera del controlador por una serie de razones:

  1. Nos gustaría volver a utilizar la consulta en otras partes de la aplicación, sin necesidad de duplicar el código del QueryBuilder.
  2. Si duplicamos el código del QueryBuilder, tendríamos que hacer varias modificaciones en el futuro si fuera necesario cambiar la consulta.
  3. La separación de la consulta y el controlador nos permitirá probar la consulta de forma independiente del controlador.

Doctrine 2 proporciona las clases Repositorio para facilitarnos esta tarea.

Repositorios de Doctrine 2

Ya te presentamos las clases Repositorio de Doctrine 2 en el capítulo anterior, cuando creamos la página show del blog. Utilizamos la implementación predeterminada de la clase DoctrineORMEntityRepositoryde Doctrine para recuperar una entidad blog desde la base de datos por medio del método find(). Debido a que queremos crear una consulta personalizada, tenemos que crear un repositorio personalizado.Doctrine 2 te puede ayudar en esta tarea. Actualiza los metadatos de la entidad Blog situados en el archivo en src/Blogger/BlogBundle/Entity/Blog.php.

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Entity/Blog.php”]

[/codesyntax]

Puedes ver que hemos especificado la ubicación del espacio de nombres de la clase BlogRepository con la que esta entidad está asociada. Puesto que ya hemos actualizado los metadatos de Doctrine 2 para la entidad Blog, es necesario volver a ejecutar la tarea doctrine:generate:entities de la siguiente manera:

$ php app/console doctrine:generate:entities Blogger

Doctrine 2 crea la clase intérprete para el BlogRepository situado en src/Blogger/BlogBundle/Repository/BlogRepository.php.

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Repository/BlogRepository.php”]

[/codesyntax]

La clase BlogRepository extiende a la clase EntityRepository la cual ofrece el método find() que utilizamos anteriormente. Por último actualiza la clase BlogRepository, moviendo el código delQueryBuilder desde el controlador Page a la clase BlogRepository.

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Repository/BlogRepository.php”]

[/codesyntax]

Hemos creado el método getLatestBlogs el cual devolverá las entradas más recientes del blog, tanto en la misma forma que lo hizo el controlador como el código QueryBuilder. En la clase Repositorio tenemos acceso directo al Generador de consultas a través del método createQueryBuilder(). También hemos añadido un parámetro $límit predeterminado para poder limitar la cantidad de resultados a devolver. El restablecimiento de la consulta es muy parecido a lo que es en el controlador. Posiblemente hayas notado que no teníamos necesidad de especificar la entidad a usar a través del método from(). Eso es porque estamos dentro del BlogRepository el cual está asociado con la entidad blog. Si nos fijamos en la implementación del método createQueryBuilder en la clase EntityRepository podemos ver que el métodofrom() es llamado para nosotros.

[codesyntax lang=”php”]

[/codesyntax]

Finalmente vamos a actualizar la acción index del controlador Page para utilizar el BlogRepository.

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Controller/PageController.php”]

[/codesyntax]

Ahora, al actualizar la página esta debe mostrar exactamente lo mismo que antes. Todo lo que hemos hecho es reconstruir el código para que las clases correctas realicen las tareas correctas.

Más sobre el modelo: Creando la entidad Comentario

Los blogs son sólo la mitad de la historia cuando se trata de la comunicación y debate de ideas. También es necesario permitir a los lectores la posibilidad de comentar las publicaciones del blog. Estos comentarios también se tienen que persistir, y relacionar con la entidad Blog puesto que un blog puede tener muchos comentarios.

Vamos a comenzar definiendo los fundamentos de la clase entidad Comment. Crea un nuevo archivo situado en src/Blogger/BlogBundle/Entity/Comment.php con el siguiente contenido:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Entity/Comment.php”]

[/codesyntax]

La mayor parte de lo que ves aquí, ya lo hemos cubierto en el capítulo anterior, sin embargo, hemos utilizado metadatos para establecer un enlace con la entidad blog. Puesto que un comentario es para un blog, hemos creado un enlace en la entidad Comment a la entidad blog a la que pertenece. Lo hicimos especificando un enlace ManyToOne destinado a la entidad blog. También especificamos que la inversa de este enlace estará disponible a través de Comments. Para crear este inversa, es necesario actualizar la entidad blog para informar a Doctrine 2 que un blog puede tener muchos comentarios. Actualiza la entidad blog ubicada ensrc/Blogger/BlogBundle/Entity/Blog.php para añadir esta asignación.

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Entity/Blog.php”]

[/codesyntax]

Hay unos cuantos cambios que debemos resaltar aquí. En primer lugar, añadimos metadatos a la propiedad $comments. Recuerda que en el capítulo anterior, no añadimos metadatos para esta propiedad, ya que no queríamos que Doctrine 2 los persistiera. Esto sigue siendo cierto, sin embargo, sí queremos que Doctrine 2 pueda llenar esta propiedad con las entidades Comentario correspondientes. Eso es lo que se logra con los metadatos. En segundo lugar, Doctrine 2 requiere que la propiedad $comments predeterminada sea un objeto ArrayCollection. Esto lo hacemos en el constructor. También, toma en cuenta la declaraciónuse para importar la clase ArrayCollection.

Puesto que ya hemos creado la entidad Comentario, y actualizado la entidad Blog, permitamos que Doctrine 2 genere los métodos de acceso. Ejecuta la siguiente tarea de Doctrine 2 como antes para alcanzar este objetivo:

$ php app/console doctrine:generate:entities Blogger

Ahora, ambas entidades deben estar actualizadas con los métodos de acceso correctos. También notarás que se ha creado la clase CommentRepository ensrc/Blogger/BlogBundle/Repository/CommentRepository.php como lo especificamos en los metadatos.

Finalmente necesitamos actualizar la base de datos para reflejar los cambios en nuestras entidades. Podríamos utilizar la tarea doctrine:schema:update de la siguiente manera para hacerlo, pero, mejor vamos a presentarte las Migraciones de Doctrine 2.

$ php app/console doctrine:schema:update –force

Migraciones de Doctrine 2

La extensión Migraciones de Doctrine 2 y el paquete no vienen con la Edición estándar de Symfony2, tenemos que instalarlas manualmente como lo hicimos con la extensión y el paquete Fixtures. Abre el archivodeps ubicado en el directorio raíz de tu proyecto y añade la extensión y el paquete Migraciones de Doctrine 2 de la siguiente manera:

[codesyntax lang=”text”]

[/codesyntax]

En seguida actualiza tus proveedores para reflejar estos cambios.

$ php bin/vendors install

Esto descargará la versión más reciente de cada uno de los repositorios desde Github y los instalará en el lugar solicitado.

Si estás usando una máquina que no tiene instalado Git tendrás que descargar e instalar manualmente la extensión y el paquete.
Extension doctrine-migrations: Descarga la versión actual del paquete migrations de GitHub y expande su contenido en: vendor/doctrine-migrations.
DoctrineMigrationsBundle: Descarga la versión actual del paquete DoctrineMigrationsBundle de GitHub y expande su contenido en: vendor/bundles/Symfony/Bundle/DoctrineMigrationsBundle.

A continuación actualiza el archivo app/autoloader.php para registrar el nuevo espacio de nombres. Debido a que las migraciones de Doctrine 2 también están en el espacio de nombres DoctrineDBAL la debes colocar por encima de la configuración actual del DoctrineDBAL existente puesto que esta especifica una nueva ruta. Los espacios de nombres son revisados ​​de arriba hacia abajo por lo tanto los espacios de nombres más específicos se deben registrar antes de los menos específicos.

[codesyntax lang=”php” title=”app/autoloader.php”]

[/codesyntax]

Ahora vamos a registrar el paquete en el núcleo situado en app/AppKernel.php.

[codesyntax lang=”php” title=”app/AppKernel.php”]

[/codesyntax]

La biblioteca de Migraciones de Doctrine 2 todavía se encuentra en estado alfa por lo tanto su uso en servidores de producción se debe desalentar, por el momento.

Ahora estamos listos para actualizar la base de datos para reflejar los cambios a la entidad. Se trata de un proceso de 2 pasos. En primer lugar tenemos que conseguir que las Migraciones de Doctrine 2 resuelvan las diferencias entre las entidades y el esquema de la base de datos actual. Esto se hace con la tarea doctrine:migrations:diff. En segundo lugar necesitamos realizar efectivamente la migración basándonos en las diferencias creadas anteriormente. Esto se hace con la tarea doctrine:migrations:migrate.

Ejecuta las 2 siguientes ordenes para actualizar el esquema de la base de datos.

$ php app/console doctrine:migrations:diff
$ php app/console doctrine:migrations:migrate

Tu base de datos ahora refleja los últimos cambios de la entidad y contiene la tabla de comentarios.

También deberías notar una nueva tabla en la base de datos llamada migration_versions. Esta almacena los números de versión de cada migración para que la tarea de migración sea capaz de ver qué versión es la base de datos actual.

Las migraciones de Doctrine 2 son una gran manera de actualizar la base de datos de producción, los cambios se pueden hacer mediante programación. Esto significa que puedes integrar esta tarea en un guión para actualizar automáticamente la base de datos cuando despliegues una nueva versión de tu aplicación. Las migraciones de Doctrine 2 también nos permiten revertir los cambios creados ya que cada migración tiene los métodos up y down. Para revertir a una versión anterior es necesario especificar el número de versión a que te gustaría regresar usando la siguiente tarea:

$ php app/console doctrine:migrations:migrate 20110806183439

Datos de prueba: Revisados

 

Ahora que ya hemos creado la entidad Comment, vamos a añadirle algunos accesorios. Siempre es buena idea añadir algunos accesorios cada vez que creas una entidad. Sabemos que un comentario debe tener una entidad Blog relacionada, de esta manera lo establecimos en los metadatos de su configuración, para ello al crear accesorios para las entidades Comentario tendremos que especificar la entidad Blog a la que pertenecen. Ya creamos los accesorios para la entidad Blog por lo tanto simplemente podríamos actualizar ese archivo para agregar las entidades Comentario. Esto puede ser manejable —por ahora, pero, ¿qué sucederá después cuando agreguemos usuarios, categorías del blog, y un montón de otras entidades a nuestro paquete? Una mejor manera sería crear un nuevo archivo para los accesorios de la entidadComentario. El problema con este enfoque es: ¿cómo podemos acceder a las entidades Blog desde los accesorios blog?

Afortunadamente esto se puede conseguir fácilmente estableciendo referencias a objetos en un archivo de accesorios donde estos pueden acceder a otros accesorios. Actualiza la entidad Blog DataFixturesubicada en src/Blogger/BlogBundle/DataFixtures/ORM/BlogFixtures.php con lo siguiente. Los cambios a destacar aquí son la extensión de la clase AbstractFixture y la implementación deOrderedFixtureInterface. También ten en cuenta las dos nuevas declaraciones use para importar esas clases:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/DataFixtures/ORM/BlogFixtures.php”]

[/codesyntax]

Añadimos las referencias a las entidades Blog a través del método AddReference(). Este primer parámetro es un identificador de referencia que puedes utilizar más tarde al recuperar el objeto. Finalmente debemos implementar el método getOrder() para especificar el orden de carga de los accesorios. Los blogs se deben cargar antes que los comentarios por lo tanto devolverá 1.

Datos de prueba Comentario

Ahora estamos listos para definir algunos accesorios para nuestra entidad Comentario. Crea un archivo de accesorios en src/Blogger/BlogBundle/DataFixtures/ORM/CommentFixtures.php y añádele el siguiente contenido:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/DataFixtures/ORM/CommentFixtures.php”]

[/codesyntax]

Al igual que con las modificaciones que hicimos a la clase BlogFixtures, la clase CommentFixtures también extiende a la clase AbstractFixture e implementa la OrderedFixtureInterface. Esto significa que también debes implementar el método getOrder(). Esta vez fijamos el valor de retorno a 2, para garantizar que estos accesorios se cargarán después de los accesorios blog.

También podemos ver cómo se están utilizando las referencias a las entidades Blog creadas anteriormente.

Ahora estamos listos para cargar los accesorios a la base de datos.

$ php app/console doctrine:fixtures:load

Mostrando comentarios

Ahora podemos mostrar los comentarios relacionados con cada entrada del blog. Empecemos actualizando el CommentRepository con un método para recuperar los comentarios aprobados más recientes de unblog.

Repositorio de comentarios

Abre la clase CommentRepository situada en src/Blogger/BlogBundle/Repository/CommentRepository.php y reemplaza su contenido con lo siguiente:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Repository/CommentRepository.php”]

[/codesyntax]

El método que debemos crear, recuperará los comentarios de un blog. Para ello tenemos que añadir una cláusula where a nuestra consulta. La cláusula where utiliza un parámetro nombrado que se ajusta con el método setParameter(). Siempre debes usar parámetros en lugar de establecer los valores directamente en la consulta, tal como:

En este ejemplo el valor de $blogId no será desinfectado y podría dejar la consulta abierta a un ataque de inyección SQL.

Controlador del Blog

A continuación necesitamos actualizar la acción show del controlador Blog para recuperar los comentarios del blog. Actualiza el controlador del Blog que se encuentra en src/Blogger/BlogBundle/Controller/BlogController.php con lo siguiente:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Controller/BlogController.php”]

[/codesyntax]

Usamos el método new en el CommentRepository para recuperar los comentarios aprobados del blog. También pasamos la colección $comments a la plantilla.

La plantilla show del Blog

Ahora que tenemos una lista de comentarios del blog, podemos actualizar la plantilla show del blog para mostrar los comentarios. Simplemente, podríamos colocar la presentación de los comentarios directamente en la plantilla show del blog, pero, debido a que los comentarios tienen su propia entidad, sería mucho mejor separar tal presentación en otra plantilla, e incluir esa plantilla. Esto nos permitiría volver a utilizar la plantilla para reproducir los comentarios en otras partes de la aplicación. Actualiza la plantilla show del blog ubicada en src/Blogger/BlogBundle/Resources/public/views/Blog/show.html.twig con lo siguiente:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Resources/public/views/Blog/show.html.twig”]

[/codesyntax]

Como puedes ver, usamos una nueva etiqueta de Twig, la etiqueta include. Esta incluirá el contenido de la plantilla especificada por BloggerBlogBundle:Comment:index.html.twig. Además le podemos pasar cualquier cantidad de argumentos a la plantilla. En este caso, le tenemos que pasar una colección de entidades Comentario para que las reproduzca.

Plantilla para mostrar Comentarios

La BloggerBlogBundle:Comment:index.html.twig que estamos incluyendo aún no existe, por lo tanto la tenemos que crear. Dado que esta sólo es una plantilla, no es necesario crear una ruta o un controlador para ella, solo necesitamos el archivo de plantilla. Crea un nuevo archivo situado en src/Blogger/BlogBundle/Resources/public/views/Comment/index.html.twig con el siguiente contenido:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Resources/public/views/Comment/index.html.twig”]

[/codesyntax]

Como puedes ver iteramos sobre una colección de entidades Comentario y mostramos los comentarios. También presentamos una de las otras agradables funciones de Twig, la función cycle. Esta función se moverá entre los valores de la matriz que se le pasa conforme avanza cada iteración del bucle. El valor de la iteración actual del bucle se obtiene a través de la variable especial loop.index0. Esta mantiene un recuento de las iteraciones del bucle, comenzando en 0. Hay una serie de otras variables especiales disponibles cuando estamos dentro de un bloque de código de bucle. También puedes notar que establecimos unID HTML para el elemento artículo. Esto, más adelante, nos permitirá crear vínculos permanentes para crear más comentarios.

CSS para mostrar comentarios

Por último vamos a añadir un poco de CSS para mantener la elegancia en los comentarios. Actualiza la hoja de estilos situada en src/Blogger/BlogBundle/Resorces/public/css/blog.css con lo siguiente:

[codesyntax lang=”css” title=”src/Blogger/BlogBundle/Resorces/public/css/blog.css”]

[/codesyntax]

Si no estás usando enlaces simbólicos para referenciar los assets en el directorio web debes volver a ejecutar la instalación de los assets para sobreescribir las modificaciones del archivo css

$ php app/console assets:install web

Si ahora echas un vistazo a una página que muestra un blog, por ejemplo, http://symblog.dev/app_dev.php/2 deberías ver los comentarios del blog.

Comentarios symblog

Añadiendo comentarios

En la última parte de este capítulo añadiremos la funcionalidad para que los usuarios agreguen comentarios a las publicaciones del blog. Esto será posible a través de un formulario en la página show del blog. Ya te presentamos la creación de formularios en Symfony2 cuando creamos el formulario de contacto. En lugar de crear manualmente el formulario de comentarios, le puedes permitir a Symfony2 que lo haga por nosotros. Ejecuta la siguiente tarea para generar la clase CommentType para la entidad Comentario.

$ php app/console generate:doctrine:form BloggerBlogBundle:Comment

De nuevo, aquí notarás el uso de la versión dura para especificar una entidad Comentario.

Posiblemente habrás notado que también está disponible la tarea doctrine:generate:form. Esta es la misma tarea solo que el espacio de nombres es diferente.

La tarea para generar el formulario ha creado la clase CommentType situada en src/Blogger/BlogBundle/Form/CommentType.php.

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Form/CommentType.php”]

[/codesyntax]

Ya hemos explorado lo que está pasando aquí cuando generamos la clase EnquiryType anterior. Ahora, podríamos empezar a personalizar este tipo, pero, primero vamos a mostrar el formulario.

Mostrando el formulario de comentarios

Nuestro primer objetivo es permitir a nuestros usuarios que agreguen comentarios desde la misma página del blog, podríamos crear el formulario en la acción show del controlador Blog y reproducir el formulario directamente en la plantilla show. Sin embargo, sería mucho mejor separar este código como lo hicimos con la visualización de los comentarios. La diferencia entre mostrar los comentarios y mostrar el formulario de comentarios es que necesitamos procesar el formulario, por lo tanto esta vez requerimos de un controlador. Esto introduce un método ligeramente diferente al anterior en el que sólo incluimos una plantilla.

Enrutando

Tenemos que crear una nueva ruta para manejar el procesamiento de los formularios presentados. Añade una nueva ruta al archivo de enrutado ubicado ensrc/Blogger/BlogBundle/Resources/config/routing.yml.

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Resources/config/routing.yml”]

[/codesyntax]

El controlador

A continuación, tenemos que crear el nuevo controlador Comment al que hemos hecho referencia anteriormente. Crea un archivo situado en src/Blogger/BlogBundle/Controller/CommentController.php con el siguiente contenido:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Controller/CommentController.php”]

[/codesyntax]

Creamos dos acciones en el controlador Comment, una para new y otra para create. La acción new tiene que ver con mostrar el formulario de comentarios, la acción create tiene que ver con el procesamiento al presentar el formulario de comentarios. Si bien esto puede parecer un gran plato de código, no hay nada nuevo aquí, ya hemos cubierto todo en el capítulo 2 cuando creamos el formulario de contacto. No obstante, antes de seguir adelante asegúrate de que entiendes completamente lo que está sucediendo en el controlador Comment.

Validando el formulario

No queremos que los usuarios puedan enviar comentarios para los blogs con valores usuario o comentario en blanco. Para lograrlo nos remontaremos a los validadores que te presentamos en la parte 2 cuando creamos el formulario de consulta. Actualiza la entidad Comentario ubicada en src/Blogger/BlogBundle/Entity/Comment.php con lo siguiente:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Entity/Comment.php”]

[/codesyntax]

Las restricciones garantizan que tanto el usuario como el comentario no deben estar en blanco. También hemos creado la opción mensaje tanto para las restricciones como para redefinir los predeterminados. Recuerda agregar los espacios de nombres ClassMetadata y NotBlank como se muestra arriba.

La vista

A continuación necesitamos crear dos plantillas para las acciones new y create del controlador. En primer lugar crea un nuevo archivo situado ensrc/Blogger/BlogBundle/Resources/public/views/Comment/form.html.twig con el siguiente contenido:

[codesyntax lang=”html4strict” title=”src/Blogger/BlogBundle/Resources/public/views/Comment/form.html.twig”]

[/codesyntax]

El propósito de esta plantilla es muy simple, sólo reproduce el formulario de comentarios. Además notarás que el método acción del formulario es POST a la nueva ruta que hemos creadoBloggerBlogBundle_comment_create.

A continuación vamos a añadir la plantilla para la vista create. Crea un nuevo archivo situado en src/Blogger/BlogBundle/Resources/public/views/Comment/create.html.twig con el siguiente contenido:

[codesyntax lang=”html4strict”]

[/codesyntax]

Como la acción create del controlador Comment trata con el procesamiento del formulario, también necesitamos poder visualizarlo, puesto que podría haber errores en el formulario. Reutilizamos elBloggerBlogBundle:Comment:form.html.twig para reproducir el formulario real y evitar la duplicidad de código.

Ahora vamos a actualizar la plantilla show del blog para reproducir el formulario añadir del blog. Actualiza la plantilla ubicada en src/Blogger/BlogBundle/Resources/public/views/Blog/show.html.twigcon lo siguiente:

[codesyntax lang=”html4strict” title=”src/Blogger/BlogBundle/Resources/public/views/Blog/show.html.twig”]

[/codesyntax]

Aquí utilizamos otra nueva etiqueta de Twig, la etiqueta render. Esta etiqueta reproducirá el contenido de un controlador en la plantilla. En nuestro caso, reproduce el contenido de la acción new del controladorBloggerBlogBundle:Comment:new.

Si ahora le echas un vistazo a una de las páginas show del blog, como http://symblog.dev/app_dev.php/2 verás que Symfony2 lanza una excepción.

Excepción comentarios Symfony2

Esta excepción es lanzada por la plantilla BloggerBlogBundle BloggerBlogBundle:Blog:show.html.twig. Si vemos de cerca la línea 25 de la plantilla BloggerBlogBundle:Blog:show.html.twig podemos ver que la siguiente línea muestra que el problema existe realmente en el proceso de integración del controlador BloggerBlogBundle:Comment:create.

Si nos fijamos un poco más en el mensaje de excepción, este nos da algo más de información sobre la naturaleza del por qué se produjo la excepción.

Las entidades pasadas al campo de elección deben tener definido un método “__toString()”

Esto nos está diciendo que un campo de elección que estamos tratando de pintar no tiene establecido un método __toString() para la entidad asociada con el campo de elección. Un campo de elección es un elemento del formulario que le da al usuario una serie de opciones, como un elemento select (desplegable). Tal vez estés preguntándote ¿dónde diablos estamos pintando un campo de elección en el formulario de comentarios? Si una vez más nos fijamos en la plantilla del formulario de comentarios te darás cuenta de que reproducimos el formulario usando la función {{ form_widget(form) }} de Twig. Esta función devuelve el formulario completo en su forma básica. Por lo tanto vamos a volver a la clase dónde creamos el formulario, la clase CommentType. Podemos ver que se añade una serie de campos al formulario a través del objeto FormBuilder. En particular, estamos agregando un campo blog.

Si recuerdas el capítulo 2, nos habló de cómo el FormBuilder trata de adivinar el tipo de campo a producir basándose en los metadatos relacionados con el campo. A medida que configuramos una relación entre los entidades Comentario y Blog, el FormBuilder ha adivinado que el comentario debe ser un campo choice, el cual permite al usuario especificar la entrada en el blog adjuntándola al comentario. Es por eso que tenemos el campo choice en el formulario, y el porqué Symfony2 está lanzando la excepción. Podemos solucionar este problema implementado el método __toString() en la entidad Blog.

[codesyntax lang=”php”]

[/codesyntax]

Los mensajes de error en Symfony2 son muy detallados describiendo el problema que se ha producido. Siempre lee los mensajes de error, ya que por lo general facilitan bastante el proceso de depuración. Los mensajes de error también proporcionan una traza completa para que puedas ver los pasos que se estaban siguiendo al producirse el error.

Ahora, al actualizar la página deberías ver aparecer el formulario de comentarios. También te darás cuenta que se han pintado algunos campos no deseados tales como approvedcreatedupdated y blog. Esto se debe a que no personalizamos la clase CommentType generada anteriormente.

Todos los campos reproducidos parece que son el tipo de campo correcto. El campos user es un campo text, el campo comment es un campo textarea, los 2 campos DateTime son una serie de campos selectque te permiten seleccionarlos para precisar la hora, etc.
Esto se debe a la habilidad del FormBuilder para adivinar el tipo de la propiedad y el campo que necesita reproducir. Este es capaz de hacerlo basándose en los metadatos que le proporciones. Puesto que hemos suministrado metadatos bastante específicos para entidad Comentario, el FormBuilder es capaz de hacer conjeturas precisas de los tipos de campo.

Ahora actualizaremos esta clase ubicada en src/Blogger/BlogBundle/Form/CommentType.php para producir únicamente los campos que necesitamos:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Form/CommentType.php”]

[/codesyntax]

Ahora, cuando actualices la página únicamente se emiten los campos usuario y comentario. Si envías ahora el formulario, el comentario en realidad no se guardará en la base de datos. Esto es porque el controlador del formulario no hace nada con la entidad Comentario si el formulario supera la validación. Entonces, ¿cómo persistimos la entidad Comentario a la base de datos? Ya has visto cómo hacerlo cuando creamos los DataFixtures. Actualiza la acción create del controlador Comentario para persistir la entidad Comentario a la base de datos.

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Controller/CommentController.php”]

[/codesyntax]

La persistencia de la entidad Comentario es tan simple como una llamada a persist() y otra a flush(). Recuerda que el formulario sólo trata con objetos PHP, y Doctrine 2 gestiona y persiste esos objetos. No hay conexión directa entre la presentación de un formulario, y la persistencia a la base de datos de la información presentada.

Ahora deberías poder añadir comentarios a las entradas del blog.

Añadir comentarios blog symfony2

Conclusión

Hemos hecho buenos progresos en este capítulo. Nuestro sitio web de blogs está empezando a funcionar más conforme a nuestras expectativas. Ahora tenemos listos los elementos básicos, la página Inicial y la entidad comentarios. Ahora un usuario puede enviar comentarios a los blogs y leer los comentarios dejados por otros usuarios. Hemos visto cómo crear accesorios a los cuales se puede hacer referencia a través de múltiples archivos y utilizar las Migraciones de Doctrine 2 para mantener en línea el esquema de la base de datos con los cambios en las entidades.

A continuación vamos a ver la construcción de la barra lateral para incluir una nube de etiquetas y comentarios recientes. También extenderemos Twig creando nuestros propios filtros personalizados. Por último vamos a ver el uso de la biblioteca de activos Assetic para que nos ayude a gestionar nuestros activos.

© Copyright 2011, dsyph3r :: Traducido por Nacho Pacheco

Partes del artículo<< [Parte 3] El modelo del Blog: Usando Doctrine 2 y accesorio[Parte 5] Personalizando la vista: extensiones Twig, la barra lateral y Assetic >>

One Response to “[Parte 4] El modelo de comentarios: repositorios y migraciones de Doctrine”

  1. xe dap xep gap

    Very good blog! Do you have any tips and hints for aspiring writers?
    I’m planning to start my own blog soon but I’m a little lost on everything.
    Would you propose starting with a free platform like WordPress or go for a paid option? There are so many
    choices out there that I’m totally overwhelmed .. Any ideas?
    Cheers!

    Responder

Deja un comentario

  • (will not be published)


2 + = 8