2011-08-03 11 views
5

¿Hay algún código de código abierto (o ejemplo) para Symfony2 que pueda filtrar cierto modelo usando múltiples parámetros? Un buen ejemplo de lo que estoy buscando se puede ver en esta página web de Trulia.Filtrando con symfony2

http://www.trulia.com/for_sale/30000-1000000_price/10001_zip/

http://www.trulia.com/for_rent/Chicago,IL/#for_rent/Chicago,IL/0-500_price/wd,dw_amenities/sm_dogs_pets"

http://www.trulia.com/for_rent/Chicago,IL/#for_rent/Chicago,IL/400-500_price/wd,dw_amenities

http://www.trulia.com/for_rent/Chicago,IL/#for_rent/Chicago,IL/wd,dw_amenities"

http://www.trulia.com/for_rent/Chicago,IL/#for_rent/Chicago,IL/400p_price/dw,cs_amenities

http://www.trulia.com/for_rent/Chicago,IL/#for_rent/Chicago,IL/1p_beds/1p_baths/400p_price/dw,cs_amenities

Observe cómo se construyen las URL al hacer clic en el formulario, supongo que está usando un controlador para todas estas rutas, ¿Cómo se hace ?. No creo que vaya a redirigir todas las rutas posibles a un controlador específico (como se muestra a continuación), ¿tal vez algún tipo de enrutamiento dinámico?

/** 
* @Route("/for_rent/{state}/{beds}_beds/{bath}_bath/{mix_price}-{max_price}_price /{amenities_list} 
* @Route("/for_rent/{state}/{mix_price}-{max_price}_price/{amenities_list} 
* @Route("/for_rent/{state}/{bath}_bath/{mix_price}-{max_price}_price/{amenities_list} 
* @Route("/for_rent/{state}/{mix_price}_price/{amenities_list} 
* @Route("/for_rent/{state}/{beds}_beds/{bath}_bath/{amenities_list}  
* ........ 
*/ 

public function filterAction($state, $beds, $bath, $min_price, $max_price ....) 
{ 
    .... 
} 

Gracias.

Respuesta

1

Para consultas simples (es decir, donde no necesita tener un rango de datos, como el valor mínimo-máximo), puede usar el repositorio de entidades para encontrar entidades por los parámetros de solicitud dados. Suponiendo que su entidad es Acme\FooBundle\Entity\Bar:

$em = $this->getDoctrine()->getEntityManager(); 
$repo = $em->getRepository('AcmeFooBundle:Bar'); 

$criteria = array(
    'state' => $state, 
    'beds' => $beds, 
    // and so on... 
); 
$data = $repo->findBy($criteria); 

Cuando la construcción de la matriz $criteria, es probable que desee algo de lógica para que sólo ordenar por criterios que se han proporcionado, en lugar de todos los valores posibles. $data contendrá todas las entidades que coincidan con los criterios.

Para consultas más complejas, querrá consultar DQL (y tal vez un custom repository) para obtener un control más detallado de las entidades que está sacando.

1

Para construir sus rutas, estoy seguro de que tenía un vistazo a la página Routing de la documentación, pero te diste cuenta que se puede poner requisitos en las rutas? This página explica cómo hacerlo con anotaciones.

En cuanto al filtrado, supongo que DQL estaría bien, pero también puede escribir SQL directamente con Doctrine y asignar los resultados de su consulta a una o más entidades. Esto se describe here. Puede ser más flexible que DQL.

+0

anotaciones le permiten regular más de una vía, que es grande, pero eso no evita que escriba manualmente todas las combinaciones posibles para todos los parámetros del filtro, es decir, que tienen parámetros ABC todas las combinaciones posibles ruta será, ABC, AB, BC, AC, que es un dolor. No sé si la implementación de su propio enrutamiento permitirá este tipo de correspondencia dinámica de URL. – csg

+1

Encontré una solución, muy simple/** * @Route ("/ search/{q}", requirements = {"q": ". +"}) * ........ */ q coincidirá todo hasta el final de la URL. Depende de usted analizar "q", más información http://symfony.com/doc/current/cookbook/routing/slash_in_parameter.html – csg

0

CSG, su solución es buena (con @Route ("/ Búsqueda/{q}) si usted sólo tiene que utilizar el enrutamiento en 'unidireccional'. Pero lo que si va a necesitar para imprimir algunos enlaces de filtro de precios en página accesible por url: http://www.trulia.com/for_sale/30000-1000000_price/10001_zip/

En caso de @Route("/search/{q} usted no será capaz de utilizar el método de ruta url generar con params

0

Hay un gran paquete llamado LexikFormFilterBundle "lexik/form-filter-bundle": "~2.0" que le ayuda a generar el complejo DQL después de la. Formulario de filtro completado por el usuario.

I c reventó un paquete, que depende de él, que cambia los tipos de un FormType dado (como el generado por SencioGeneratorBundle). De modo que puede visualizar el FilterForm correcto y luego crear el DQL después de él (con Lexik).

puede instalarlo con el compositor, siguiendo este README.md

único que hace es anular el Tipo Doctrina del Adivino, que sugiere que el FormType requerida para cada campo Entidad, y sustituir el Tipo propuesta por el LexikFormFilterType adecuada. Por ejemplo, reemplaza un simple NumberType por un filter_number que se representa como dos números, límites de intervalo máximo y mínimo.

private function createFilterForm($formType) 
{ 
    $adapter = $this->get('dd_form.form_adapter'); 
    $form = $adapter->adaptForm(
     $formType, 
     $this->generateUrl('document_search'), 
     array('fieldToRemove1', 'fieldToRemove2') 
    ); 
    return $form; 
} 

Al enviar el formulario, solo se lo pasa a Lexik y ejecuta la consulta generada, como se muestra en mi ejemplo.

public function searchAction(Request $request) 
{ 
    // $docType = new FormType/FQCN() could do too. 
    $docType = 'FormType/FQCN'; 
    $filterForm = $this->createFilterForm($docType); 
    $filterForm->handleRequest($request); 

    $filterBuilder = $this->getDocRepo($docType) 
     ->createQueryBuilder('e'); 
    $this->get('lexik_form_filter.query_builder_updater') 
     ->addFilterConditions($filterForm, $filterBuilder); 

    $entities = $filterBuilder->getQuery()->execute(); 

    return array(
     'entities' => $entities, 
     'filterForm' => $filterForm->createView(), 
    ); 
}