gildonei / filter_results
CakePHP 插件,用于向控制器和视图添加 PRG 过滤器
Requires
- php: >=5.6
README
从搜索表单生成 CakePHP 2.3+ 的 conditions 以供 find 方法使用。
兼容性
兼容 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;- 重构所有结构方法;
安装
Composer
composer require gildonei/filter_results:"2.3.x-dev"
手动下载
下载插件并将其内容放置在 /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,将自动配置分页。
- 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));
准备好了!我们有一个可以按姓名过滤用户并兼容分页的字段。
还有更多,过滤结果会自动分解过滤值以获得更好的结果。例如:如果我们通过 '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 中输入 '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));
现在,您可以首先选择字段(Filter Results 表格会自动列出字段),然后输入运算符和过滤条件的期望值。
在某些情况下,您可能需要自定义选择字段和运算符。例如,我们可以只留下 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 (kristian.tenfen@gmail.com)