使用symfony2过滤

时间:2011-08-03 16:26:40

标签: php url-routing symfony

Symfony2是否有任何开源(或示例)代码可以使用多个参数过滤某些模型?在这个Trulia网页上可以看到我正在寻找的一个很好的例子。

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

请注意在单击表单时是如何构建URL的,我想是对所有这些路由使用一个控制器,它是如何完成的? 我不认为它会将所有可能的路由重定向到特定的控制器(如下所示),也许某种动态路由?

/**
 * @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 ....)
{
    ....
}

感谢。

4 个答案:

答案 0 :(得分:1)

对于简单查询(即,您不需要具有数据范围,例如最小 - 最大值),您可以使用实体存储库通过给定的请求参数查找实体。假设您的实体是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);

构建$criteria数组时,您可能需要一些逻辑,以便您只按提供的条件排序,而不是按所有可能的值排序。然后,$data将包含符合条件的所有实体。

对于更复杂的查询,您需要查看DQL(可能还有custom repository),以便对您提取的实体进行更细粒度的控制。

答案 1 :(得分:1)

要构建您的路线,我确定您查看了文档的Routing页面,但您是否注意到您可以对路线提出要求? This页面解释了如何使用注释进行操作。

至于过滤,我认为DQL没问题,但您也可以使用Doctrine直接编写SQL,并将查询结果映射到一个或多个实体。这被描述为here。它可能比DQL更灵活。

答案 2 :(得分:0)

csg,你的解决方案很好(使用@Route(“/ search / {q}),如果你只需要在”单向“中使用路由。但是如果你需要在页面上打印一些价格过滤器链接怎么办?可通过网址访问: http://www.trulia.com/for_sale/30000-1000000_price/10001_zip/

如果是@Route("/search/{q},您将无法使用params生成路由方法url。

答案 3 :(得分:0)

有一个名为LexikFormFilterBundle "lexik/form-filter-bundle": "~2.0"的很棒的Bundle可以帮助您在用户完成Filter表单后生成复杂的DQL。

我创建了一个依赖于它的Bundle,它改变了给定FormType的类型(比如SencioGeneratorBundle生成的那个)。所以你可以显示正确的FilterForm,然后在它之后创建DQL(使用Lexik)。

您可以使用Composer按照此README.md

进行安装

它所做的只是覆盖Doctrine Type Guesser,它为每个Entity字段建议所需的FormType,并用适当的LexikFormFilterType替换给定的Type。例如,用NumberType替换一个简单的filter_number,它将两个数字,Max和Min间隔边界呈现。

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

在表单提交后,您只需将其提供给Lexik并运行生成的查询,如我的示例所示。

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(),
    );
}