Symfony 5: La Vía Rápida. Otra vez el Paso 9

Reescribiendo el Paso 9

El objetivo de esta entrada, es tratar de explicar como instalar y configurar EasyAdmin 3 con Symfony 5, que a esta altura (Octubre de 2020), ya va por la versión 5.1.7 y parece pronta a salir la versión 5.2, y aplicarlo al proyecto Guestbook.

Habíamos comentado en una entrada anterior, que quienes sigan el libro de Potencier «Symfony 5: La Vía Rápida», se iban a encontrar con un problema al intentar aplicar las instrucciones del libro, que está pensado para la versión de EasyAdmin 2.* y no para la versión 3.

Quedan entonces dos opciones: instalar esta versión más vieja de EasyAdmin que es la que se desarrolla en el libro, o intentar adecuar la nueva versión de EasyAdmin, la número 3, al contexto del proyecto desarrollado por Potencier en su libro. Yo elegí finalmente la segunda opción, y trataré de explicar a continuación como procedí para instalar, personalizar y configurar EasyAdmin 3, en el marco del proyecto Guestbook desarrollado en el libro, «Symfony 5: La Vía Rápida». Los comentarios que permitan mejorar estas explicaciones, son bienvenidos. Ya hay circulando en Internet videos y explicaciones escritas sobre la instalación de EasyAdmin 3, pero ninguna adaptada al caso del libro. Ese vacío trataré de llenar con esta entrada.

Instalar EasyAdmin 3 en el proyecto Guestbook

Partimos del supuesto que hemos terminado el Paso 8 del libro, donde se instaló Doctrine ORM, fueron creadas las entidades Conference y Comment y enlazamos las mismas, vinculando cada comentario a una conferencia en particular. Finalmente, se realizó la migración de la base de datos, dando lugar cada entidad a una nueva tabla con el mismo nombre, en nuestra base de datos. Gráficamente:

Imagen 1

Ahora vamos a instalar el bundle EasyAdmin 3. Posicionados en la carpeta del proyecto, y tal como lo pide el libro, ejecutamos desde la CLI el comando:

symfony composer req admin

A continuación, debemos instalar al menos un Dashboard. Lo hacemos con el comando siguiente:

symfony console make:admin:dashboard

En el proceso de instalación se nos hacen un par de preguntas, contestamos las opciones por defecto. El proceso queda graficado en la imagen siguiente:

Imagen 2

Como vemos en la propia imagen, nos invitan a generar los controladores CRUD. En nuestro caso son dos como mínimo, para gestionar cada entidad que tenemos que son Conference y Comment.

Pero antes cabría preguntarse que significa CRUD. Encontramos esta sencilla explicación en la web, (sin que hallamos guardado la fuente para citarla):

El concepto CRUD está estrechamente vinculado a la gestión de datos digitales. CRUD hace referencia a un acrónimo en el que se reúnen las primeras letras de las cuatro operaciones fundamentales de aplicaciones persistentes en sistemas de bases de datos:

  • Create (Crear registros)
  • Read bzw. Retrieve (Leer registros)
  • Update (Actualizar registros)
  • Delete bzw. Destroy (Borrar registros)

En pocas palabras, CRUD resume las funciones requeridas por un usuario para crear y gestionar datos. Varios procesos de gestión de datos están basados en CRUD, en los que dichas operaciones están específicamente adaptadas a los requisitos del sistema y de usuario, ya sea para la gestión de bases de datos o para el uso de aplicaciones.

Luego de instalar el primer Dashboard, podemos escribir en nuestro navegador la dirección:

http://127.0.0.1/admin

Se cargará una pantalla similar a la siguiente (se muestra una parte), donde nos ayudan a seguir adelante con la generación de los CRUD controllers:

Imagen 3

Primero tenemos que completar el contenido del archivo editándolo:

src\Controller\Admin\DashboardController.php

Nos pide incorporar varios métodos que en realidad ya se instalaron automáticamente cuando generamos el Dashboard, siendo los que faltarían, los siguiente:

use EasyCorp\Bundle\EasyAdminBundle\Router\CrudUrlGenerator;
use App\Entity\Conference;
use App\Entity\Comment;

Creamos ahora los CRUD controllers:

symfony console make:admin:crud

Nos preguntará para cual de las dos entidades que tenemos creadas, deseamos crear un CRUD. Elegimos Conference tal como muestra la imagen siguiente (opción 1), y luego nos realizan dos preguntas, donde optamos por las opciones por defecto:

Imagen 4

repetimos el comando para crear ahora el CRUD para los comentarios, o sea para la entidad Comment:

symfony console make:admin:crud

La siguiente captura de pantalla, muestra el proceso completo de generación de los dos CRUD por consola:

Imagen 5

Ahora que contamos con los archivos básicos, tenemos que proceder a adaptarlos a nuestras necesidades. Empezaremos por trabajar con el archivo que contiene el Dashboard: DashboardController.php

Continuamos leyendo las instrucciones que teníamos en la página:

http://127.0.0.1/admin

En especial, nos interesa ahora esta parte:

Imagen 6

En la imagen siguiente está el código del Dashborard que en la sección de los métodos ya tiene incorporado:

use EasyCorp\Bundle\EasyAdminBundle\Router\CrudUrlGenerator;

Faltan agregar:
use App\Entity\Conference;
use App\Entity\Comment;

Como vemos, hay tres funciones ya creadas en forma automática: index, configureDashboard y configureMenuItems, y sobre las tres tenemos cambios que realizar:

Imagen 7

En la primera función, cambiamos el contenido return parent::index(); por este otro (sugerido en las instrucciones que vimos más arriba):

$routeBuilder = $this->get(CrudUrlGenerator::class)->build();    
return $this->redirect($routeBuilder->setController(ConferenceCrudController::class)->generateUrl());

Es decir, que elegimos como página de inicio del Administrador, el CRUD de Conference.

En la segunda función solo vamos cambiar el título de la página de inicio de del Administrador. Elegimos Guestbook Admin

En la tercera función, como su propio nombre lo indica, tenemos que configurar los items que compondran el menú del Administrador. Ponemos tres: un link a la página principal del proyecto. Un segundo link al CRUD de conferencias (Conference) y un tercer link al CRUD de comentarios (Comment). El resultado completo de los cambios del archivo DashboardController.php se muestra en las imágenes 8 y 9. La imágen 8, muestra los métodos que tienen que estar habilitados. La imagen 9, muestra el código de las funciones.

Imagen 8

El resultado del nuevo código para las funciones es:

Imagen 9

Las dos imágenes combinadas, muestran el archivo completo DashboardController.php

Este código se ve así en http://127.0.0.1/admin

Imagen 10

Mostramos la página con varios registros ya caragados como muestra. Aquí hay mucho para mejorar, pero hemos logrado que se visualice una de las entidades, Conference, que nos permite: crear una nueva conferencia, editar una conferencia existente, borrar o eliminar (Delete). Y también contamos con un buscador. Podremos construir filtros y personalizar las columnas. Esa será nuestra siguiente tarea.

Personalizando los CRUD

Hemos generado como parte del proceso de instalación del Bundle EasyAdmin 3, dos CRUD, que son archivos con los controladores, para manejar cada una de las entidades desde el administrador. Uno de los archivos es para la entidad Conference y otro para la entidad Comment. Ambos archivos se encuentran aquí:

src\Controller\Admin\ConferenceCrudController.php

src\Controller\Admin\CommentCrudController.php

Empecemos por analizar el archivo ConferenceCrudController.php tal como fue instalado por el Bundle:

Imagen 11

La Imágen 11, muestra el aspecto incial que presenta después de generarlo desde la CLI. Las columnas que aparecen en la Imágen 10, son seleccionadas automáticamente, pero nos gustaría personalizarlas. Por ejemplo: Cambiar los títulos de las columnas. Sacar la columna ID, que no debería ser vista ni modificada por nadie, ni siquiera el administrador, ya que alteraría todo el sistema. Por otro lado, nos gustaría que la columna «Is International» (recordemos que es un campo tipo Boolean), no tenga el número 1 para cuando es verdadero el valor y esté vacía cuando es falso el valor. Nos gustaría, además, para más información, agegar el total de comentarios de cada conferencia como una columna adicional. ¿Desde donde se hace todo esto? Editando el archivo que estamos analizando. Una vez hecho estos cambios, la pantalla de la conferencias en nuestro browser, tendrá el siguiente aspecto:

Imagen 12

Y esto se debe al siguiente código:

Imagen 13

Es muy importante notar que cada ítem que queremos personalizar, tiene una denominación del tipo de campo que se trata, seguido del título de la columna. Por ejemplo, para la primer columna que muestra la ciudad de la conferencia, que se trata de un campo texto (varchar) escribimos dentro de la función configureFields:

yield TextField::new(‘city’, ‘City’);

A su vez, en la parte superior donde se definen los métodos, agregamos:

use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;

Y así con cada tipo de campo. Debemos especificar en la función configureFields el tipo de datos que contiene la entidad (y su tabla) y en los métodos definidos en parte superior del controlador, la sentencia que llame al método correspondiente a ese tipo de campo. Para cada tipo de campo, necesitamos definir un método correspondiente.

Veamos ahora el caso de la entidad Comment. El CRUD original está contenido en el archivo CommentCrudController.php y su código es el siguiente:

Imagen 14

Pero así como está, si queremos visualizar el listado de los comentarios, nos lleva al siguiente error:

Imagen 15

Este es un caso más complejo. Tiene al menos dos complicaciones, 1) formatear adecuadamente el campo fecha createdAt para evitar el error que se muestra en la Imágen 15, y 2) definir un tratamiento distinto para el campo de texto photoFilename, según que estemos en la opción de listado (donde queremos ver la foto) o edición (donde queremos ver el nombre del archivo de la foto). Como primer paso, vemos que hay que modificar el formato del campo fecha para que pueda ser adecuadamente mostrado.

yield DateTimeField::new(‘createdAt’, ‘Created’)->setFormat(‘dd-MM-y HH:mm:ss’)
->setSortable(true)->setFormTypeOption(‘disabled’,’disabled’);

Notamos aquí una gran diferencia respecto a la configuración de los campos de la entidad Conference. Vemos que es posible personalizar en varios aspectos los campos que lo requieran. En el caso del campo fecha createdAt especificamos el formato de fecha y hora que queremos visualizar en el listado con:

->setFormat(‘dd-MM-y HH:mm:ss’)

Habilitamos la posibilidad de ordenar la columna en ambos sentidos, ascendente o descendente:

->setSortable(true)

Y, finalmente, determinamos que cuando se pase al modo de edición, el campo no se puede editar. Es de solo lectura. Esto lo hacemos con:

->setFormTypeOption(‘disabled’,’disabled’)

Otro campo de manejo bastante complejo que requiere nuestra atención es photoFilename. Este campo, es un campo texto, que lleva el nombre de los archivos con las imágenes subidas por los visitantes que dejaron un mensaje en Guestbook. Suponemos que queremos otorgar al administrador, en el modo edición (Edit) el poder de decidir si una imagen es pertinente y queda tal como la subió el visitante, o por el contrario, no se la considera adecuada y por lo tanto eliminamos su nombre de archivo para que no sea visible la imagen.

Para poder hacer esto con el campo photoFilename necesitamos definir dos variables auxiliares, que llamamos:

$avatar = ImageField::new(‘photoFilename’)->setBasePath(‘uploads/photos/’)->setLabel(‘Photo’);
$avatarTextFile = TextField::new(‘photoFilename’);

Estas dos variables la usamos del siguiente modo:

if (Crud::PAGE_INDEX === $pageName) {
yield ImageField::new(‘photoFilename’)->setBasePath(‘uploads/photos/’)->setLabel(‘Photo’);
} elseif (Crud::PAGE_EDIT === $pageName) {
yield TextField::new(‘photoFilename’)->setLabel(‘Photo’);
}

Recordemos también que para cada tipo de campo, tenemos que definir un método al inicio del archivo.

El nuevo código se muestra en las tres siguientes imágenes:

Imagen 16
Imagen 17
Imagen 18

Y lo visualizamos en nuestro Browser así, en el modo listado (Read):

Imagen 19

Mientras que en el modo edición (Edit) se vería así el formulario (por ejemplo para el tercer registro del listado):

Imagen 20

Vemos que conseguimos lo que pretendíamos: el campo de fecha es de solo lectura y el campo photoFilename pasa a mostrar el nombre del archivo y no la imagen.

Pero un verdadero CRUD no estaría completo si no podemos hacer alguna selección de los registros. Por ejemplo, seleccionar solo los registros de una determinada conferencia y/o según el estado del comentario. Crearemos estos dos filtros y mostraremos su funcionamiento.

El manejo de los filtros para los comentarios, se hace dentro del archivo CommentCrudController.php a través de la función:

public function configureFilters(Filters $filters): Filters
{
return $filters
->add(‘conference’)
->add(‘state’);
}

Y su aspecto es el siguiente( mostramos dos imágenes) una con los filtros desplegados y seleccionados pero todavía no aplicados, y la siguiente imagen, con el filtro aplicado donde hemos seleccionado las condiciones siguientes: para la conferencia: Amsterdan 2019 y para el estado: submitted (o sea, los comentarios enviados pero todavía no aprobados para su publicación).

Imagen 21

Una vez hecha la selección de las condiciones de filtrado, hacemos clic con el mouse en botón Apply y quedara el nuevo listado acotado solo a los registros que queremos ver:

Imagen 22

En la imagen 22, puede verse recuadrado en rojo, el sector de la pantalla desde donde se manejan los filtros.

Bien, con esto hemos visto lo básico del Bundle EasyAdmin 3 y su incorporación al proyecto Guestbook, desarrollado en el libro «Symfony 5: La Vía Rápida».

Quedaría por asegurar el acceso al administrador definiendo un usuario y contraseña, pero esto se hace igual que en la versión anterior del Bundle, por lo que el capítulo 15 del libro, titulado: «Paso 15: Asegurando el panel de administración» sigue siendo válido para esta versión del Bundle.

Deja un comentario