Trabajando con filtros en Symfony (II)

JP Juan Pablo Romero Juan Pablo Romero

Juan Pablo Romero

Software Engineer
3 min read.

Esta es una segunda entrega acerca del trabajo con los formularios de filtro en Symfony. He tenido en cuenta los comentarios y sugerencias de  los visitantes del blog,  así que esta entrega integrará el uso de Doctrine.

Antes de comenzar,  aclaro que mucha de la información aquí consignada está basada en el código generado por el generador de administración tanto de Propel como de Doctrine y desde luego en la documentación del API de Symfony 1.2.

Filtros con Doctrine

En la entrada anterior hablé del uso de los formularios con Propel de manera básica y aunque las forma de trabajar los formularios de filtros con Doctrine no es muy diferente, haré algunas aclaraciones importantes.

Al momento de generar el modelo con Doctrine, con la tarea:

php symfony doctrine:build-all

al igual con con Propel, se genera en el directorio  lib/filter/doctrine/ el conjunto de clases de formularios de filtro. Tomando como referencia el esquema de datos del tutorial de Jobeet (Día 3 - http://www.symfony-project.org/jobeet/1_2/Doctrine/en/03) los filtros generados son:

BaseFormFilterDoctrine.class.php
JobeetAffiliateFormFilter.class.php
JobeetCategoryAffiliateFormFilter.class.php
JobeetCategoryFormFilter.class.php
JobeetJobFormFilter.class.php
base/

Estas clases podemos modificarlas según nuestras necesidades, al igual que con los formularios. Ahora, vamos a generar el módulo que permita el CRUD de las ofertas de trabajo (Tabla Jobeet_Job):

php symfony doctrine:generate-module frontend job JobeetJob

Bien, ahora con el módulo generado, vamos a revisar  las acciones y hacer los ajustes para el uso de los filtros. En primera forma, debemos modificar la acción index, para que nos presente el formulario de filtros:

class jobActions extends sfActions
// apps/frontend/modules/job/actions/actions.class.php
{
  public function executeIndex(sfWebRequest $request)
  {
    $this->jobeet_job_list = Doctrine::getTable('JobeetJob')
    $this->createQuery('a')
    $this->execute();
    $this->filtro = new JobeetJobFormFilter();
  }

// más código .....

Al igual que con Propel, debemos crear una instancia del filtro, para que sea visualizada en la plantilla:

// apps/frontend/modules/job/templates/indexSuccess.php

<h1>Lista de trabajos</h1>


<h1>Lista de trabajos</h1>

<form action="<?php echo url_for('job/filter'); ?>" method="post">


<input class="ui-state-default ui-corner-all" type="submit" value="Filtrar">
   '_reset', 'method' => 'post')); ?>
 
</form>

<!--   más código html ... -->

Creamos nuestra acción encargada de filtrar los resultados (filter):

// apps/frontend/modules/job/actions/actions.class.php

public function executeFilter(sfWebRequest $request)
{
  $this->filtro = new JobeetJobFormFilter();
  $this->consulta = $this->filtro->buildQuery($request->getParameter('jobeet_job_filters'));
  $this->jobeet_job_list = $this->consulta->execute();
  $this->setTemplate('index');
}

Una de las diferencias importantes con Propel, es el método que se encarga de construir la consulta según el valor de los filtros,  que es buildQuery y que recibe una arreglo de valores a partir de los cuales se construirá la consulta. Este método devuelve un objeto de tipo Doctrine_Query, por eso llamamos al método execute en forma posterior.

Con lo anterior tenemos un sistema de filtros muy básico usando Doctrine como ORM.

Adaptando el filtro

Hasta el momento, ya hemos visto como establecer un filtro, tanto si usamos Propel como Doctrine. Sin embargo, la mayoría de las veces los campos por los cuales deseamos filtrar información no corresponden con todos los de la tabla. El filtro por defecto que se genera contempla todos los campos y por ello es necesario que hagamos algunas modificaciones, para filtrar por los campos deseados.

Siguiendo con el ejemplo del tutorial de Jobeet, supongamos que sólo queremos filtrar la lista de trabajos, por categoría  y tipo (campos category y type, respectivamente), para ello debemos modificar el método configure de la clase JobeetJobFormFilter:

// lib/form/doctrine/JobeetJobFormFilter.class.php

class JobeetJobFormFilter extends BaseJobeetJobFormFilter
{
  public function configure()
  {
   $this->setWidgets(array(
    'category_id'  => new sfWidgetFormDoctrineChoice(array('model' => 'JobeetCategory', 'add_empty' => true)),
    'type'         => new sfWidgetFormFilterInput()
   ));

    $this->setValidators(array(
    'category_id'  => new sfValidatorDoctrineChoice(array('required' => false, 'model' => 'JobeetCategory', 'column' => 'id')),
    'type'         => new sfValidatorPass(array('required' => false))
   ));
   $this->widgetSchema->setNameFormat('jobeet_job_filters[%s]');
 }
}

Cómo se puede observar, un formulario de filtro es muy similar a un formulario, con algunas diferencias en cuanto a los widgets que se usan y algunos de los métodos.  Con esta modificación, cuando imprimamos el filtro en la plantilla, ahora sólo los campos de categoría y tipo estarán disponibles.  También podemos usar los métodos setLabel y setLabels para cambiar el nombre de las etiquetas que aparecerán al momento de imprimir el formulario de filtros, por ejemplo:

$this->getWidgetSchema()->setLabels(array(
   'category_id' => 'Categoria',
   'type' => 'Tipo'
));

Uno de los widgets de filtros que considero más útiles es sfWidgetFormFilterDate, ya que con él es posible filtrar información por rangos de fecha, aquí un ejemplo de su uso para el campo de expiración de la oferta de trabajo (campo expires_at):

'expires_at'   => new sfWidgetFormFilterDate(array(
                 'from_date' => new sfWidgetFormDate(),
                 'to_date' => new sfWidgetFormDate(),
                 'with_empty' => 0,                   // Para que no salga el checkbox
                 'template' => 'desde %from_date% hasta %to_date%'
                ))

Bien, hasta aquí esta segunda entrega del trabajo con filtros en Symfony 1.2. Espero que sea  de utilidad.


Written by Juan Pablo Romero

JP Juan Pablo Romero Juan Pablo Romero

Juan Pablo designs and builds robust software solutions with a focus on performance and usability. His problem-solving skills and attention to detail ensure high-quality and efficient applications.

Newsletter

Subscribe to our newsletter:

Read more

Backups con rsync

Para algunos de nuestros clientes tenemos planes de copias de seguridad de sus archivos mas importantes, luego de probar much...

1 min read.

Build Once. Own Forever.