darxide-pl/cakephp-filter

用于 CakePHP 的扩展 FormHelper 的查询过滤插件

安装: 67

依赖: 0

建议者: 0

安全: 0

星标: 0

关注者: 1

分支: 0

开放问题: 0

类型:cakephp-plugin

1.0 2019-03-18 20:52 UTC

This package is auto-updated.

Last update: 2024-09-21 20:43:48 UTC


README

安装

您可以使用 composer 将此插件安装到您的 CakePHP 应用程序中。

安装 composer 包的推荐方式是

composer require darxide-pl/cakephp-filter

简介

在实际应用中,根据用户输入进行查询过滤可能会迅速增长成由大量输入控制的庞大查询。

此插件的主要思想是保持代码整洁和易读。

每个查询都可以在 App\Model\Filter 命名空间中作为分离的方法具有多个过滤器,查询作为参数传递给这些过滤器,因此过滤器易于测试和维护。

插件允许您使用 GET 变量、POST 变量和 JSON 输入来过滤查询。

插件还实现了在会话中(可选)的过滤器“内存”以及易于扩展的接口,以帮助您编写自己的实现。

还有 FilterForm 辅助工具,它有助于构建带有过滤器的表单。

快速示例

  1. 命令: ./bin/cake plugin load Filter
  2. /src/View/AppView.php 中加载辅助工具
<?php

namespace App\View;
use Cake\View\View;

class AppView extends View
{
    public function initialize()
    {
        $this->loadHelper('Filter.FilterForm');
    }
}
  1. 在您的 Table 类中使用 Filter\FilterAwareTrait (注意:这需要创建一个表或使用现有的一个)(注意2:特质需要在类声明中声明 use)示例文件是 /src/Model/Table/UsersTable.pgp
<?php
namespace App\Model\Table;
use Filter\FilterAwareTrait;
// rest of used classes and traits...

class UsersTable extends Table
{
    use FilterAwareTrait;
    // rest of code ...
}
  1. /src/Model/Filter/ 中创建名为 UsersFilter.php 的文件
<?php

namespace App\Model\Filter;
use Filter\Filter\BaseFilter;
use Cake\ORM\Query;

class UsersFilter extends BaseFilter
{
	/**
	* ! Used filter methods should be listed in this property - without this - filter will not be executed
	* @var  array
	*/
	protected $filters = [
		'name',
		'role'
	];

	/**
	* By default, filter will look for variable $_GET[filter][name] or $_POST[filter][name] in this case
	* @see Filter\Engine\RequestEngine::get() 
	*
	*  
	* Notice: filter will be executed only if value is not "falsy": 
	*  - not 0, 
	*  - not empty string, 
	*  - not null, etc
	* 
	* @return Query
	*/
	public function name(Query $query, string $value) :Query
	{
		return $query
			->where([
				'Users.name LIKE' => '%'.$value.'%'
			]);
	}
	
	/**
	* Filter users list by role id
	* @return Query
	*/
	public  function role(Query $query, int $role_id) :Query
	{
		return $query->where(['Users.role_id'  => $role_id]);
	}
}
  1. 现在,我们可以在控制器中将该过滤器绑定到查询,并对该查询进行分页(例如在 /src/Controller/PagesController.php 中)
<?php  

namespace App\Controller;
use App\Model\Filter\UsersFilter;

class PagesController extends AppController
{
	public  function display(...$path)
	{
		$this->loadModel('Users');
		$query =  $this
			->Users
			->find()
			->setFilterClass(UsersFilter::class);

		$results =  $this->paginate($query);
		$this->set(compact('results'));
		
		$this
			->viewBuilder()
			->setTemplate('filter_example');
	}
}
  1. 最后一步是 HTML 表单模板。创建 /src/Template/Pages/filter_example.ctp 文件
<?=  $this->FilterForm->create('Users') ?>
<?=  $this->FilterForm->control('name') ?>
<?=  $this->FilterForm->end() ?>

<?php dump($results->toArray()) ?>

文档

1. 用例

1.1 为不同用户类型过滤相同查询

有时我们需要为不同用户类型禁用一些过滤器字段。

我们可以通过许多方式实现这一点,我们应该考虑一些可能性。

如果过滤器复杂且用户和管理员表单之间的差异很大,我们可以为每种用户类型创建单独的过滤器类:/src/Model/Filter/Users/AdminsFilter.php /src/Model/Filter/Users/CustomersFilter.php

然后在控制器中,我们可以像快速示例中那样将预期的过滤器绑定到查询。

注意:上面两行,我们将过滤器类移动到一个更深层次的文件夹树中。唯一的区别是传递给创建 FormFilter 的参数应该如下所示

<?= $this->FilterForm->create('Users.Customers') ?>

或者

<?= $this->FilterForm->create('Users.Admins') ?>

如果用户类型之间的差异很小,您可以在过滤器中使用会话:在我们的 /src/Model/Filter/UsersFilter.php

<?php

namespace App\Model\Filter;
use Filter\Filter\BaseFilter;
use Cake\ORM\Query;

class UsersFilter extends BaseFilter
{
	protected $filters = ['name'];
	
	public  function name(Query $query, string $value) :Query
	{
		if($this->getSession()->read('Auth.User.role') !==  'admin') {
			return $query;
		}

		return $query
			->where([
				'Users.name LIKE'  =>  '%'  . $value .  '%'
			]);
	}
}

1.2 在另一个过滤器方法内部获取一个过滤器方法的值

我们可以通过使用获取器简单地实现这一点:FilterInterface::get(string $name)

<?php

namespace App\Model\Filter;
use Filter\Filter\BaseFilter;
use Cake\ORM\Query;

class UsersFilter extends BaseFilter
{
	protected $filters = ['name','lastname'];
	
	public  function name(Query $query, string $value) :Query
	{
		// we can access value of get.filter.lastname|post.filter.lastname here
		$lastname = $this->get('lastname');
		
		return $query
			->where([
				'Users.name LIKE'  =>  '%'  . $value .  '%',
				'Users.lastname LIKE' => '%' . $value . '%'
			]);
	}
	
	public function lastname (Query $query, string $value) :Query {}
}

1.3 在过滤器中访问数据库

我认为我们应该避免这种操作,但这种情况确实发生了。有时在过滤之前,我们需要从数据库中获取一些数据,只为准备最终的过滤查询。

<?php

namespace App\Model\Filter;
use Filter\Filter\BaseFilter;
use Cake\ORM\Query;

class UsersFilter extends BaseFilter
{
	protected $filters = ['name'];
	
	public  function name(Query $query, string $value) :Query
	{
		// We can load model like in controller 
		$this->loadModel('Roles');
		$roles = $this->Users->find('list')->toArray();
		
		return $query
			->where([
				'Users.name LIKE'  =>  '%'  . $value .  '%',
				'Users.role_id IN' => $roles
			]);
	}
}