miércoles, 4 de septiembre de 2013

Lista de tareas simple con Symfony 2: Parte 2

Vamos a continuar con la creación de la página principal de nuestra lista de tareas.

Controlador de la página principal

Después de definir la entidad, crear su tabla correspondiente en la base de  datos y de añadir algunos datos de prueba, ya podemos implementar nuestro controlador. Para ello vamos a asociar la ruta de la que será nuestra página principal, con el controlador que se va a encargar de tratar con el modelo y renderizar la vista. Por lo que vamos a modificar el fichero ListaCompraBundle/Resources/config/routing.yml .

Por norma, el nombre de un controlador (clase) llevará el sufijo Controller  y nombre de la acción (método de la clase) llevará el sufijo Action.

El controlador encargado de tratar el patrón de ruta '/' va a ser ListadoController.php y  el método, que invocará el controlador, encargado de ejecutar la acción va a ser indexAction. Además le indicaremos que el acceso a dicha ruta se realizará mediante peticiones GET.

 #src/Tarea/ListadoBundle/Resources/config/routing.yml  
 homepage:  
   pattern: /  
   defaults: { _controller: TareaListadoBundle:Tarea:index }  
   requirements:  { _method: "GET" }  

Es importante eliminar o comentar la entrada 'welcome' en app/config/routing.yml (creado por Symfony a modo de ejemplo), ya que usará sobre el patrón de ruta '/' y puede interferir con nuestro Bundle.

Nota: Fíjate en el patrón que se utiliza para especificar la acción del controlador: TareaListadoBundle:Listado:index . A esto se le llama en Symfony2 nombre lógico del controlador. Está compuesto por el nombre del bundle, el nombre del controlador, y el nombre de la acción separados por el carácter ':' (bundle:controlador:metodo). En este caso, el nombre lógico hace referencia a el método indexAction() de una clase PHP llamada Tarea\ListadoBundle\Controller\Listado.

1. TareaController versión 1

 //src/Tarea/ListadoBundle/Controller/TareaController.php  
 <?php  
 namespace Tarea\ListadoBundle\Controller;  
 use Symfony\Bundle\FrameworkBundle\Controller\Controller;  
 class TareaController extends Controller  
 {  
   public function indexAction()  
   {  
     $em = $this->getDoctrine()  
           ->getEntityManager();  
     $tareas = $em->createQueryBuilder()  
           ->select('t')  
           ->from('TareaListadoBundle:Tarea', 't')  
           ->getQuery()  
           ->getResult();  
     return $this->render('TareaListadoBundle:Tarea:listado.html.twig', array(  
       'tareas' => $tareas  
     ));  
   }  
 }  

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 Tarea a través del TareaListadoBundle:Tarea (recuerda que esto hace lo mismo que Tarea\ListadoBundle\Entity\Tarea).
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 Tarea.

A pesar de que puedes realizar las consultas (sobre 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:
- Nos gustaría volver a utilizar la consulta en otras partes de la aplicación, sin necesidad de duplicar el código del QueryBuilder.
- Si duplicamos el código del QueryBuilder, tendríamos que hacer varias modificaciones en el futuro si fuera necesario cambiar la consulta.
- La separación de la consulta y el controlador nos permitirá probar la consulta de forma independiente del controlador.

2. Repositorio

Doctrine 2 proporciona las clases Repositorio para facilitarnos esta tarea. Debido a que queremos crear una consulta personalizada, tenemos que crear un repositorio personalizado. Doctrine 2 te puede ayudar en esta tarea.
Para ello, tendremos que actualizar los metadatos de la entidad Tarea, creada en el tutorial anterior, situados en el archivo en src/Tarea/listadoBundle/Entity/Tarea.php.
Habrá de modificar los metadados del principio, donde asociamos la entidad con la tabla:

  /**   
  * @ORM\Entity   
  * @ORM\Table(name="tarea")   
  */   
  class Tarea {   
  }  

Por estos, donde especificaremos la ubicación del espacio de nombres de la clase TareaRepository (repositorio) con la que esta entidad está asociada.

 /**  
  * @ORM\Entity(repositoryClass="Tarea\ListadoBundle\Entity\TareaRepository")  
  * @ORM\Table(name="tarea")  
  */  

Puesto que ya hemos actualizado los metadatos de Doctrine 2 para la entidad tarea, es necesario volver a ejecutar la tarea doctrine:generate:entities de la siguiente manera:

 $ php app/console doctrine:generate:entities Tarea  

Y Symfony 2 nos habrá creado el armazón del repositorio de Tarea en \Entity, junto a la definición de la entidad. Por lo tanto, podemos completar la clase TareaRepository trasladando a dicha clase el código del QueryBuilder desde el controlador TareaController.

 //src/Tarea/ListadoBundle/Entity/TareaRepository.php  
 <?php  
 namespace Tarea\ListadoBundle\Entity;  
 use Doctrine\ORM\EntityRepository;  
 class TareaRepository extends EntityRepository  
 {  
    public function getTareas()  
   {  
     $qb = $this->createQueryBuilder('t')  
           ->select('t')  
           ->addOrderBy('t.fechaRealizar', 'ASC')  
           ->addOrderBy('t.prioridad', 'DESC');  
     return $qb->getQuery()  
          ->getResult();  
   }  
 }  

Nota: en la clase repositorio tenemos acceso directo al generador de consultas a través del método createQueryBuilder().  Además no tenemos necesidad de especificar la entidad a usar a través del método from(). Eso es porque estamos dentro del TareaRepository el cual está asociado con la entidad Tarea.

3. TareaController versión 2

Ahora vamos a modificar el método indexAction() del controlador para poder utilizar el método creado en el repositorio.

 //src/Tarea/ListadoBundle/Controller/Controller.php  
 <?php  
 namespace Tarea\ListadoBundle\Controller;  
 use Symfony\Bundle\FrameworkBundle\Controller\Controller;  
 class TareaController extends Controller  
 {  
   public function indexAction()  
   {  
     $em = $this->getDoctrine()  
           ->getEntityManager();  
     $tareas = $em->getRepository('TareaListadoBundle:Tarea')  
            ->getTareas();  
     return $this->render('TareaListadoBundle:Tarea:listado.html.twig', array(  
       'tareas' => $tareas  
     ));  
   }  
 }  

Podríamos sustituir el return final por print_r($tareas); y así probar que obtenemos el listado de tareas. Aunque al no devolver un objeto Response dará error. Pero el print_r mostrará lo que queríamos ver.


Entradas relacionadas

Lista de tareas simple con Symfony 2: Parte 1
Introducción a Symfony 2

No hay comentarios:

Publicar un comentario