【问题标题】:Filtering with symfony2使用 symfony2 过滤
【发布时间】:2011-08-03 16:26:39
【问题描述】:

是否有任何 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 ....)
{
    ....
}

谢谢。

【问题讨论】:

    标签: php url-routing symfony


    【解决方案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),以便对您要提取的实体进行更细粒度的控制。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 注解允许你匹配多个路由,这很好,但这并不能避免你手动为所有过滤器参数编写所有可能的组合,我的意思是,拥有 ABC 参数所有可能的路由组合将be,ABC,AB,BC,AC,这是一种痛苦。我不知道实现自己的路由是否会允许这种动态的 URL 匹配。
      • 找到了解决办法,很简单 /** * @Route("/search/{q}", requirements={"q": ".+"}) * ...... .. */ q 然后将匹配所有内容,直到 URL 的末尾。然后由你来解析“q”,更多信息symfony.com/doc/current/cookbook/routing/…
      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        有一个很棒的 Bundle,叫做 LexikFormFilterBundle "lexik/form-filter-bundle": "~2.0",它可以帮助您在用户完成过滤器表单后生成复杂的 DQL。

        我创建了一个依赖于它的 Bundle,它可以更改给定 FormType 的类型(例如由 SencioGeneratorBundle 生成的类型),因此您可以显示正确的 FilterForm,然后在它之后创建 DQL(使用 Lexik)。

        您可以使用 Composer 安装它,遵循 README.md

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

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

        【讨论】:

          猜你喜欢
          • 2016-08-16
          • 2014-06-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多