CakePHP - 构建搜索 - 如何在查询中包含URL变量

时间:2011-04-10 06:27:48

标签: php cakephp cakephp-1.3

我正在构建一个搜索页面,其中包含许多不同的搜索参数,用户可以点击这些参数,这将传递URL中的变量。

$this->Restaurant->recursive = 1;
$this->paginate = array(
    'conditions' => array(
        'City.name' => $this->params['url']['city'],
        'Cuisine.name' => $this->params['url']['cuisine'],
    ),
);
$data = $this->paginate('Restaurant');
$this->set('data', $data);

如果在URL中有?city = newyork& cuisine = pizza - 这可以正常工作 - 但如果没有,则会出错*如果它是普通的PHP,我会将查询构建为字符串并仅附加条件如果存在变量......等等。但是对于Cake,我不知道从哪里开始,或者最好的方法是什么。

修改

*如果我没有将'city'或'cuisine'作为URL变量传递,我明白了:

<b>Notice</b> (8)</a>: Undefined index:  city [<b>APP/controllers
/restaurants_controller.php</b>, line <b>18</b>

...

City.name'&nbsp;=&gt;&nbsp;$this-&gt;params['url']['city'],
</span></code></span></pre></div><pre class="stack-trace">
RestaurantsController::search() - APP/controllers/restaurants_controller.php
, line 18
Dispatcher::_invoke() - CORE/cake/dispatcher.php, line 204
Dispatcher::dispatch() - CORE/cake/dispatcher.php, line 171
[main] - APP/webroot/index.php, line 83

如果我只有“城市”和“美食”这不会有问题 - 但如果我计划再以同样的方式传递20个搜索选项,我希望能够通过它们或者不是由我自己决定,而不是每次都被迫在URL中强制使用ALL。

2 个答案:

答案 0 :(得分:1)

你是什么意思errors out

通常在视图中的分页调用之前添加$this->Paginator->options(array('url' => $this->passedArgs));会使蛋糕将所有传递的URL参数添加到它生成的网址

修改

您要查找的是命名参数:http://book.cakephp.org/view/947/Named-parameters

如果你看一下最后一个例子,你会看到路线映射到ContentsController->view();,你可以选择在passedArgs数组中选择发送所有参数。

URL: /contents/view/chapter:models/section:associations
Mapping: ContentsController->view();
$this->passedArgs['chapter'] = 'models';
$this->passedArgs['section'] = 'associations';
$this->params['named']['chapter'] = 'models';
$this->params['named']['section'] = 'associations';

编辑2

这里的问题是你有一组可变的搜索条件。您的系统应基本完成搜索条件,并根据选择的过滤器构建搜索查询。有几种方法可以解决这个问题。最简单的方法是循环使用它们。

$allowsFilters = array('city' => 'Model.city', 'name' => 'Model.name', 'price' => 'Model.price'); //list of allowed keys to search on. 
$opts  = array();
foreach ($this->params['named'] as $filter => $value)  {
    if (isset($allowsFilters[$filter])) {
         $opts[$allowsFilters[$filter]] = $value; 
    }
}
$findOpts = array('conditions' => $opts)
$this->Model->find('all', $findOpts);

这样,您就可以将一组可以应用的过滤器列入白名单。然后你遍历params并构建你的conditions数组。如果需要OR条件或不同的MYSQL,则必须稍微修改一下。但这将允许您拥有可变数量的过滤器。

答案 1 :(得分:1)

蛋糕使用MVC模式,意味着像http://localhost/controller/action/param1/param2这样的网址 转换为index.php?controller = controller&amp; action = action&amp; param1 = pararm1 ...

如果你无法从原始网址获取查询字符串(http://localhost/controller.../?a = 3&amp; b = 2) 你应该将QSA参数添加到.htaccess中,它应该看起来像那样

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [**QSA**,L]
</IfModule>

然后您将获得操作方法的查询字符串。

如果您不想使用这种方式,您可以通过控制器的操作使用

获取参数
$arg_list = func_get_args();

代替查询字符串

它看起来像那样

Controller Pages{
  public function search(){
    $args = func_get_args();
    foreach($args as $arg){
       // build query string for the search, depending on the params you got
    }
    // do search
  }

}