在symfony 2中搜索功能的最佳方式

时间:2013-02-15 13:33:08

标签: php symfony search-engine

我的网站上有一个用elasticsearch实现的搜索功能。 现在我对设计有一点疑问。

我有searchAction路由/search,它在查询字符串中包含一个参数。与/search?terms=...一样。

我想将结果列表过滤掉,但我对正确的设计有一些疑问。

制作过滤结果列表的最佳解决方案是什么?

如果我传递filter参数,我需要使用当前url指定表单操作,并将当前查询字符串附加为链接,对吧? 例如:

<form action="{{ current_pat }} ~ {{ query_string }}" method="post">
    <input type="checkbox" name="filter_one">....

在这种情况下,网址会像:/search?terms=...$post我有过滤器。这是正确的解决方案,还是更好的链接列表? 例如:

<ul>
    <li><a href="{{current_path}} ~ {{ query_string }} ~ {{ this_filter }}">... 
    <li><a href="{{current_path}} ~ {{ query_string }} ~ {{ this_another_filter }}">
...

在这种情况下,网址将如下:/search?terms=...&this_filter=...

在带有get参数和后置过滤器的表单中,我需要在搜索操作中使用这两种类型的参数。这好吗?

相反,链接现在会在$get请求中包含所有参数,但我不喜欢在模板中使用查询字符串构建网址。

最好的方法是什么?

3 个答案:

答案 0 :(得分:2)

  

将KNP paginator捆绑包与搜索操作一起使用。在搜索表单上对post中的searchAction进行post操作,并在使用匹配条件对数据进行排序后,重新呈现页面。

public function searchAction(Request $request,array $arguments = array())
        {
            $em = $this->getDoctrine()->getManager();
            $paginator = $this->get('knp_paginator');
            $parameter = $request->get('board_search');
            $boardRepo = $this->getDoctrine()->getRepository('PNCMISDashboardBundle:ExaminationBoards')->loadBoardByName($parameter);
            $boards = $paginator->paginate($boardRepo, $this->get('request')->query->get('page', 1), 10);
            return $this->render('PNCMISDashboardBundle:ExaminationBoards/CRUD:index.html.twig', array(
                    'boards'=> $boards,
                )
            );
        }


public function loadBoardByName($name)
    {
        $q = $this
            ->createQueryBuilder('boards')
            ->where('upper(boards.name) LIKE upper(:search)')
            ->setParameter('search', '%'.$name.'%')
            ->getQuery()
        ;
        try {
            // The Query::getSingleResult() method throws an exception
            // if there is no record matching the criteria.
            $user = $q->getResult();
        } catch (NoResultException $e) {
            throw new UsernameNotFoundException(sprintf('Unable to find an board identified by "%s".', $name), null, 0, $e);
        }
        return $user;
    }

答案 1 :(得分:0)

我更喜欢查询字符串中的所有参数,这些参数允许用户为网址添加书签或通过电子邮件发送。

答案 2 :(得分:0)

这取决于。

1如果您不需要索引(例如搜索引擎优化 - 谷歌机器人)过滤结果页面,在我看来,您应该使用AJAX来实现这一目标。

路由:

search_result:
    pattern: /search
    defaults:  { _controller: AcmeExampleBundle:Ajax:searchResult }
    requirements:
        _method:  POST

JavaScript(伪代码)

filterResults() {
    var queryString = $('input#toSearch').val();
    var filters = new Object();
    filters['someKey'] = someVal;
    $.post('/search', {filters: filters, queryString: queryString}, function(data) {
        $('#resultList').html(data);
    });)
}

当然,你不应该对url'/ search'进行编码。

控制器:

// src/Acme/ExampleBundle/Controller/AjaxController.php
    // ...
    public function searchResultAction()
    {
        $filters = $this->getRequest()->get('filters', array());
        $searchObject = new searchObj(); 
        // or smt like $this->get('service_name'); if you use search object as service
        // you can also use entity manager
        $searchObject->setQueryString($this->getRequest()->get('queryString'));
        $searchObject->setFilters($filters);
        return $this->render('AcmeExampleBundle:Ajax:searchResult.html.twig', array(
            'records' => $searchObject->getResults()
        ));
    }

当然你可以返回json响应,但在我看来,返回准备注入部分模板是最简单的管理

观看:

{% for record in records %}
    <div class="record">{{ record.title }}</div>
{% endfor %}

2如果您想索引过滤结果页面,则应使用用户友好的URL而不是AJAX方法

路由:

search_result:
    pattern: /search/{queryString}/{make}/{model}
    defaults:  { _controller: AcmeExampleBundle:Ajax:searchResult }
    requirements:
        _method:  GET

控制器:

// src/Acme/ExampleBundle/Controller/AjaxController.php
    // ...
    public function searchResultAction($queryString, $make, $model)
    {
        $filters = array('make' => $make, 'model' => $model);
        $searchObject = new searchObj(); 
        // or smt like $this->get('service_name'); if you use search object as service
        // you can also use entity manager
        $searchObject->setQueryString($queryString);
        $searchObject->setFilters($filters);
        return $this->render('AcmeExampleBundle:Ajax:searchResult.html.twig', array(
            'records' => $searchObject->getResults()
        ));
    }