hevertonfreitas / filter_results
从搜索表单生成查找 CakePHP 2.3+ 中方法的条件
Requires
- cakephp/cakephp: ^2.3
README
从搜索表单生成 conditions 以在 CakePHP 2.3+ 中查找方法。
兼容性
与 CakePHP 2.3 + Paginate (组件) 兼容
- CakePHP 1.3 版本的版本:http://github.com/pedroelsner/filter_results/tree/1.3
- CakePHP 2.0 版本的版本:http://github.com/pedroelsner/filter_results/tree/2.0
2.3 版本中的更改
FilterResultsComponent已更改为FilterComponent;FilterFormHelper已更改为SearchHelper;- 重新反思所有结构方法;
安装
下载插件并将其内容放置在 /app/Plugin/FilterResults 或其他 CakePHP 插件目录中。
激活
通过添加文件 /app/Config/bootstrap.php 来激活插件
CakePlugin::load('FilterResults');
配置
编辑文件 /app/AppController.php
var $components = array(
'FilterResults.Filter' => array(
'auto' => array(
'paginate' => false,
'explode' => true, // recommended
),
'explode' => array(
'character' => ' ',
'concatenate' => 'AND',
)
)
);
var $helpers = array(
'FilterResults.Search' => array(
'operators' => array(
'LIKE' => 'containing',
'NOT LIKE' => 'not containing',
'LIKE BEGIN' => 'starting with',
'LIKE END' => 'ending with',
'=' => 'equal to',
'!=' => 'different',
'>' => 'greater than',
'>=' => 'greater or equal to',
'<' => 'less than',
'<=' => 'less or equal to'
)
)
);
设置参数
- auto->paginate: 如果您设置为 TRUE,Paginate 将自动配置。
- auto->explode: 如果您设置为 TRUE,则筛选值将被
explode->character分解,并通过explode->concatenate连接。
使用组件
以下示例将基于以下数据库构建
CREATE TABLE groups (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(200) NOT NULL,
PRIMARY KEY(id),
UNIQUE(name)
) ENGINE=INNODB;
CREATE TABLE users (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
group_id INT UNSIGNED NOT NULL,
name VARCHAR(200) NOT NULL,
username VARCHAR(20) NOT NULL,
active TINYINT(1) NOT NULL DEFAULT 1,
PRIMARY KEY(id),
FOREIGN KEY(group_id) REFERENCES groups(id),
UNIQUE(username)
) ENGINE=INNODB;
INSERT INTO groups(name) VALUES('Admin');
INSERT INTO groups(name) VALUES('Guest');
INSERT INTO users(group_id, name, username) VALUES(1, 'Pedro Elsner', 'pelsner');
INSERT INTO users(group_id, name, username) VALUES(1, 'Petter Morato', 'pmorato');
INSERT INTO users(group_id, name, username, active) VALUES(2, 'Lucas Pedro Mariano Elsner', 'lpmelsner', 0);
INSERT INTO users(group_id, name, username, active) VALUES(2, 'Rebeca Moraes Silva', 'rebeca_moraes', 0);
INSERT INTO users(group_id, name, username, active) VALUES(2, 'Silvia Morato Moraes', 'silvia22', 0);
简单筛选
好的,在 Bake 生成屏幕后,我们在网格(表格)上放置了一个筛选器来按名称(User.name)搜索用户。所以让我们设置控制器和视图,如下所示
文件 /app/Controller/UsersController.php
function index() {
// Add filter
$this->Filter->addFilters(
array(
'filter1' => array(
'User.name' => array(
'operator' => 'LIKE',
'value' => array(
'before' => '%', // optional
'after' => '%' // optional
)
)
)
)
);
$this->Filter->setPaginate('order', 'User.name ASC'); // optional
$this->Filter->setPaginate('limit', 10); // optional
// Define conditions
$this->Filter->setPaginate('conditions', $this->Filter->getConditions());
$this->User->recursive = 0;
$this->set('users', $this->paginate());
}
这里的设置相当简单:我们创建了一个名为 filter1 的筛选器,它将使用字段 User.name。此筛选器使用 LIKE 操作符,在要筛选的内容前后添加 %。
现在我们只需在表的顶部创建一个表单。
文件 /app/View/Users/index.ctp)
echo $this->Search->create();
echo $this->Search->input('filter1');
echo $this->Search->end(__('Filter', true));
准备好了!我们有一个可以根据名称筛选用户并兼容 Paginate 的字段。
而且更多,筛选结果自动分解筛选值以获得更好的结果。例如:如果我们通过 'Pedro Elsner' 进行筛选,条件将是:WHERE ((User.name LIKE '%Pedro%') AND (User.name LIKE '%Elsner%'))
分解设置
对于 LIKE 和 NOT LIKE 操作符的 explode 选项始终在筛选结果设置中启用。但您如何知道,您可以在控制器声明中禁用它。如果您这样做,则可以仅针对指定的筛选器启用 explode 函数。
$this->Filter->addFilter(
array(
'filter1' => array(
'User.name' => array(
'operator' => 'LIKE',
'explode' => true
)
)
)
);
也可以为每个筛选器更改分解参数。
$this->Filter->addFilter(
array(
'filter1' => array(
'User.name' => array(
'operator' => 'LIKE',
'explode' => array(
'character' = '-',
'concatenate' = 'OR'
)
)
)
)
);
您还可以使用分解函数与任何操作符(如 =)一起使用。参见
$this->Filter->addFilter(
array(
'filter1' => array(
'User.name' => array(
'operator' => '=',
'explode' => true
)
)
)
);
简单筛选 + 组合规则
现在让我们在筛选器 filter1 中创建另一个规则。我们想要通过名称(User.name)或用户名(User.username)进行筛选。
然后只需更改我们的控制器
文件 /app/Controller/UsersController.php
$this->Filter->addFilters(
array(
'filter1' => array(
'OR' => array(
'User.name' => array('operator' => 'LIKE'),
'User.username' => array('operator' => 'LIKE')
)
)
)
);
OR 规则也可以是 AND 或 NOT。
注意:如果您定义了多个条件而没有特定的规则,则插件将自动理解 AND。
简单筛选 + 固定规则
假设现在我们的筛选器 filter1 在提供信息时应按名称(User.name)筛选,并且仅筛选活动用户。
文件 /app/Controller/UsersController.php
$this->Filter->addFilters(
array(
'filter1' => array(
'User.name' => array('operator' => 'LIKE'),
'User.active' => array('value' => '1')
)
)
);
筛选聚合
过滤器结果自动通过规则AND连接所有过滤器。以下示例中,如果filter1中包含'informe' 'Pedro',且filter2中包含'elsner',我们将得到以下条件:WHERE (User.name LIKE '%Pedro%') AND (User.usernname LIKE '%elsner%')
$this->Filter->addFilters(
array(
'filter1' => array(
'User.name' => array('operator' => 'LIKE')
)
'filter2' => array(
'User.username' => array('operator' => 'LIKE')
)
)
);
注意:我们也可以通过规则OR和NOT来连接过滤器。
现在,我们将通过规则OR连接filter1和filter2,如果filter1不为空,则仅对活跃用户进行过滤。因此,我们将得到以下条件:WHERE ((User.name LIKE '%Pedro%') AND (User.active = 1)) OR (User.usernname LIKE '%elsner%')
$this->Filter->addFilters(
array(
'OR' => array(
'filter1' => array(
'User.name' => array('operator' => 'LIKE'),
'User.active' => array('value' => '1')
)
'filter2' => array(
'User.username' => array('operator' => 'LIKE')
)
)
)
);
选择过滤器
让我们更改过滤器。除了按名称过滤外,我们现在还可以通过一个选择的字段按用户组(Group.name)进行过滤。
文件 /app/Controller/UsersController.php
function index() {
// Add filter
$this->Filter->addFilters(
array(
'filter1' => array(
'User.name' => array('operator' => 'LIKE')
),
'filter2' => array(
'User.group_id' => array(
'select' => $this->Filter->select('Grupo', $this->User->Group->find('list'))
)
)
)
);
// Define conditions
$this->Filter->setPaginate('conditions', $this->Filter->getConditions());
$this->User->recursive = 0;
$this->set('users', $this->paginate());
}
文件 /app/View/Users/index.ctp
echo $this->Search->create();
echo $this->Search->input('filter2', array('class' => 'select-box'));
echo $this->Search->input('filter1');
echo $this->Search->end(__('Filter', true));
准备好了!随意使用和滥用这些过滤器。
为了清楚起见,请查看此图片。这里我们有一个产品视图,您可以按:颜色、尺寸、重量、材料和产品名称进行过滤。
高级过滤器
在某些情况下,我们可能需要一些与示例不同的事情,例如,我们希望用户选择要执行过滤的字段和运算符。
文件 /app/Controller/UsersController.php
function index() {
// Add filter
$this->Filter->addFilters('filter1');
// Define conditions
$this->Filter->setPaginate('conditions', $this->Filter->getConditions());
$this->User->recursive = 0;
$this->set('users', $this->paginate());
}
注意:请注意,这次我们过滤filter1没有任何参数。这是因为规则是在视图中选择的。
文件 /app/View/Users/index.ctp
echo $this->Search->create();
echo $this->Search->selectFields('filter1', null, array('class' => 'select-box'));
echo $this->Search->selectOperators('filter1');
echo $this->Search->input('filter1');
echo $this->Search->end(__('Filter', true));
现在,您首先可以选择字段(过滤器结果表将自动列出字段),然后通知运算符和过滤器所需的价值。
将会有需要自定义字段和运算符进行选择的情况。例如,让我们只保留字段User.id、User.name和User.username进行选择,运算符为LIKE和=。
为此,我们只更改视图。
文件 /app/View/Users/index.ctp
echo $this->Search->create();
echo $this->Search->selectFields('filter1',
array(
'User.id' => __('ID', true),
'User.name' => __('Name', true),
'User.username' => __('Username', true),
),
array(
'class' => 'select-box'
)
);
echo $this->Search->selectOperators('filter1',
array(
'LIKE' => __('containing', true),
'=' => __('equal to', true)
)
);
echo $this->Search->input('filter1');
echo $this->Search->end(__('Filter', true));
运算符
过滤器结果有预定义的运算符,以下将列出您可以在高级过滤器中使用的所有选项。
array(
'LIKE' => __('containing', true),
'NOT LIKE' => __('not containing', true),
'LIKE BEGIN' => __('starting with', true),
'LIKE END' => __('ending with', true),
'=' => __('equal to', true),
'!=' => __('different', true),
'>' => __('greater than', true),
'>=' => __('greater or equal to', true),
'<' => __('less than', true),
'<=' => __('less or equal to', true)
);
在...
要使用运算符BETWEEN
$this->Filter->addFilters(
array(
'filter1' => array(
'User.id' => array(
'operator' => 'BETWEEN',
'between' => array(
'text' => __(' and ', true)
)
)
)
)
);
HABTM 关系
默认情况下,CakePHP HABTM 关系会进行多次咨询,然后合并结果到一个array中。你可能已经注意到了这一点,如果没有,请检查在HABTM 关系中find()时的调试窗口。
为了过滤这些关系,我们需要创建一些“黑客”来生成单个CakePHP select,这样插件就可以通过简单的where命令过滤结果。
要创建这些“黑客”所需的所有信息和解释,可以在以下葡萄牙语教程中找到: http://pedroelsner.com/2012/09/pesquisando-em-associacoes-habtm-no-cakephp/
版权和许可
版权 2012,Pedro Elsner (http://pedroelsner.com/)
在Creative Commons 3.0下许可 (http://creativecommons.org/licenses/by/3.0/)
感谢
- Vinícius Arantes (vinicius.big@gmail.com)
- Francys Reymer (francys.reymer@gmail.com)
- Geazy El-Hanã de Oliveira (geazi.oliveira@jacotei.com.br)
- 克里斯蒂安·滕芬 (kristian.tenfen@gmail.com)