codekanzlei/cake-list-filter

列表过滤器组件/助手,用于轻松创建CRUD列表

v2.0.0 2019-06-04 16:52 UTC

This package is auto-updated.

Last update: 2024-08-29 03:58:01 UTC


README

CakePHP 3 List Filter Plugin

License Build Status

这是一个 CakePHP 3 插件,它提供了一种轻松创建 CRUD 列表过滤器的简单方法。插件将动态渲染必要的标记,并动态操作控制器的 $paginate 配置。

安装

composer require "codekanzlei/cake-list-filter": "dev-master"

在你的应用的 config/bootstrap.php 中加载插件

Plugin::load('ListFilter', ['bootstrap' => false, 'routes' => false]);

在你的 AppController 中,或者你想要使用 ListFilter 的控制器中,加载 ListFilterComponentListFilterHelper

public $helpers = [
    'ListFilter.ListFilter'
];

public $components = [
    'ListFilter.ListFilter'
];

用法

你可以在发生分页的控制器中直接定义可过滤的字段。这确保了只能使用你配置的字段进行搜索,这也自动生成了必要的表单。

你可以将字段定义为控制器中的 $listFilter 属性,或者实现一个 getListFilters() 回调方法。

在单个控制器中可以存在多个 listFilters,因为配置是根据控制器动作分离的。在这个例子中,我们假设你希望在控制器动作 index 中有一个 ListFilter。

 public $listFilters = [
     'index' => [
         'fields' => [
             'Posts.title' => [
                 'searchType' => 'wildcard',
                 'inputOptions' => [
                     'label' => 'Post Title'
                 ]
             ]
         ]
     ]
 ];

通过回调方法配置 ListFilters 提供了更多的灵活性,因为它允许执行在类属性中不可能执行的代码。

public function getListFilters($action) {
    $filters = [];
    if ($action == 'index') {
        $filters = [
            'fields' => [
                'Posts.title' => [
                    'searchType' => 'wildcard',
                    'inputOptions' => [
                        'label' => __('posts.title')
                    ]
                ],
                'Posts.author_id' => [
                    'searchType' => 'select',
                    'options' => $this->Posts->Authors->find('list'),
                    'inputOptions' => [
                        'label' => __('posts.author')
                    ]
                ]
             ]
        ];
    }
    return $filters;
}

我们假设 index 控制器动作看起来像这样

public function index()
{
    $this->paginate['contain'] = ['Authors'];
    $posts = $this->paginate($this->Posts);
    $this->set('posts', $posts);
}

现在,在你的 index.ctp 视图文件中,你可以这样渲染过滤器框

<?= $this->ListFilter->renderFilterbox() ?>

你的过滤器框将看起来像这样

filterbox

选项

searchType

这可以是以下之一

  • wildcard:执行带有给定字符串的 LIKE 搜索
  • select:渲染包含 options 配置键选项的下拉列表。只能使用此数组配置键来过滤,因此不可能进行 URL 操作。
  • multipleselect:与 select 类似,但渲染一个允许多选的下拉列表。
  • fulltext:将给定搜索词通过空格分割,并确保所有这些词都通过 LIKE 存在于字段中。
    • searchFields:如果指定此数组,将搜索多个字段
    • termsCallback:一个回调函数,它接收包含搜索词的数组并必须返回一个数组。可以用来影响搜索逻辑。

inputOptions

这些选项将用于使用 FormHelper::input() 渲染表单字段。因此,在这里,你可以设置标签、向输入添加类等。

searchTermsConjunction

设置组件时,你可以提供一个额外的选项数组来覆盖默认配置。特别是 searchTermsConjunction,默认为 'AND',意味着在全文搜索中多个术语将以 AND 连接添加到分页条件中,以缩小搜索结果。

如果你希望通过 OR 连接术语来扩大结果,你可以这样设置组件

public $components = [
    'ListFilter.ListFilter' => [
        'searchTermsConjunction' => 'OR'
    ]
];

处理多对多关系

为了处理多对多关系,例如 Users BelongsToMany Groups,你必须构建一个自定义查询并将其传递给分页器,因为分页器默认不能处理多对多关系。

public function index()
{
    $this->paginate['contain'] = ['Users'];
    $query = $this->Users->query();
    if (isset($this->paginate['conditions']['Users.group_id'])) {
        $groupId = $this->paginate['conditions']['Users.group_id'];
        unset($this->paginate['conditions']['Users.group_id']);
        $query->matching('Groups', function ($q) use ($groupId) {
            return $q->where(['Group.id' => $groupId]);
        });
    }
    $users = $this->paginate($query);
    $this->set(compact('users'));
}

自定义

如果您需要为filterbox创建自定义布局,您可以按照自己的意愿单独构建filter box。listFilter中的每个元素都可以单独渲染

<?= $this->ListFilter->openForm(); ?>
<?= $this->ListFilter->openContainer(); ?>
<div class="row">
    <div class="col-md-4">
        <?= $this->ListFilter->filterWidget('Projects.user_id'); ?>
    </div>
    <div class="col-md-4">
        <?= $this->ListFilter->filterWidget('Objects.customer_id'); ?>
    </div>
    <div class="col-md-4">
        <?= $this->ListFilter->filterWidget('Projects.status'); ?>
    </div>
</div>

<?= $this->ListFilter->filterButton(); ?>
<?= $this->ListFilter->resetButton(); ?>
<?= $this->ListFilter->closeContainer(); ?>
<?= $this->ListFilter->filterWidget('Projects.fulltext_search', [
    'inputOptions' => [
        'label' => false,
        'placeholder' => __('projects.search'),
        'prepend' => '<i class="fa fa-search"></i>'
    ]
]) ?>
<?= $this->ListFilter->closeForm(false, false); ?>

此外,您可以通过调用ListFilterHelper::config()并使用您的覆盖来操作默认的模板和类。以下是可用的选项

protected $_defaultConfig = [
    'formOptions' => [],
    'includeJavascript' => true,
    'templates' => [
        'containerStart' => '<div{{attrs}}>',
        'containerEnd' => '</div>',
        'toggleButton' => '<a{{attrs}}><i class="fa fa-plus"></i></a>',
        'header' => '<div class="panel-heading">{{title}}<div class="pull-right">{{toggleButton}}</div></div>',
        'contentStart' => '<div{{attrs}}>',
        'contentEnd' => '</div>',
        'buttons' => '<div class="submit-group">{{buttons}}</div>'
    ],
    'containerClasses' => 'panel panel-default list-filter',
    'contentClasses' => 'panel-body',
    'toggleButtonClasses' => 'btn btn-xs toggle-btn',
    'title' => 'Filter',
    'filterButtonOptions' => [
        'div' => false,
        'class' => 'btn btn-xs btn-primary'
    ],
    'resetButtonOptions' => [
        'class' => 'btn btn-default btn-xs'
    ]
];