过滤器
index
页面的列表可以使用过滤器进行细化,过滤器是一系列表单控件,用于向查询添加条件(例如,price > 10
, enabled = true
)。使用你的仪表盘或CRUD 控制器的 configureFilters()
方法定义你的过滤器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
namespace App\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Config\Filters;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
class ProductCrudController extends AbstractCrudController
{
// ...
public function configureFilters(Filters $filters): Filters
{
return $filters
->add('title')
->add('price')
->add('published')
;
}
}
EasyAdmin 为最常见的需求(日期、数值、集合等)提供了即用型过滤器。过滤器类型会根据属性的数据类型自动选择,但你也可以显式定义过滤器类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
namespace App\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Config\Filters;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Filter\BooleanFilter;
class ProductCrudController extends AbstractCrudController
{
// ...
public function configureFilters(Filters $filters): Filters
{
return $filters
->add('title')
->add('price')
// most of the times there is no need to define the
// filter type because EasyAdmin can guess it automatically
->add(BooleanFilter::new('published'))
;
}
}
内置过滤器
以下是 EasyAdmin 提供的内置过滤器
ArrayFilter
:默认应用于数组字段。它被渲染为一个<select>
列表,其中包含条件(等于/不等于)和另一个<select>
标签输入,用于引入比较值。BooleanFilter
:默认应用于布尔字段。它被渲染为标记为“是”和“否”的两个单选按钮。ChoiceFilter
:它被渲染为一个带有选项的<select>
列表。ComparisonFilter
:带有两个字段的通用复合过滤器。DatetimeFilter
:分别默认应用于 datetime、date 或 time 字段。它被渲染为一个<select>
列表,其中包含条件(之前/之后/等等)和一个浏览器原生日期选择器,用于选择日期/时间。EntityFilter
:应用于具有 Doctrine 关联的字段(支持所有类型)。它被渲染为一个<select>
列表,其中包含条件(等于/不等于/等等)和另一个<select>
列表,用于选择比较值。NullFilter
:默认情况下不应用于任何字段。它对于根据属性的“null”或“not null”值过滤结果很有用。它被渲染为用于 null 和 not null 选项的两个单选按钮。NumericFilter
:默认应用于数字字段。它被渲染为一个<select>
列表,其中包含条件(更高/更低/等于/等等)和一个<input>
,用于定义比较值。TextFilter
:默认应用于字符串/文本字段。它被渲染为一个<select>
列表,其中包含条件(包含/不包含/等等)和一个<input>
或<textarea>
,用于定义比较值。
自定义过滤器
如果你的需求更具体,你可以创建自己的过滤器。过滤器是使用两个类定义的
- 实现
EasyCorp
的配置类用于配置过滤器选项,并在过滤器处于活动状态时应用搜索条件;\Bundle \EasyAdminBundle \Contracts \Filter \FilterInterface - 实现
Symfony\Component\Form\FormType
的表单类用于渲染 HTML 小部件,这些小部件用于在应用程序中输入过滤器数据。
你可以在你的过滤器配置类中使用 FilterTrait
,以避免实现所有常用方法。这样,你只需要实现 apply()
方法,该方法是更改 $queryBuilder
对象以应用过滤器所需的查询子句的方法。
考虑这个示例,它创建了一个带有某些特殊值的自定义日期过滤器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
// src/Controller/Admin/Filter/DateCalendarFilter.php
namespace App\Controller\Admin\Filter;
use App\Form\Type\Admin\DateCalendarFilterType;
use Doctrine\ORM\QueryBuilder;
use EasyCorp\Bundle\EasyAdminBundle\Contracts\Filter\FilterInterface;
use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
use EasyCorp\Bundle\EasyAdminBundle\Dto\FilterDataDto;
use EasyCorp\Bundle\EasyAdminBundle\Filter\FilterTrait;
class DateCalendarFilter implements FilterInterface
{
use FilterTrait;
public static function new(string $propertyName, $label = null): self
{
return (new self())
->setFilterFqcn(__CLASS__)
->setProperty($propertyName)
->setLabel($label)
->setFormType(DateCalendarFilterType::class);
}
public function apply(QueryBuilder $queryBuilder, FilterDataDto $filterDataDto, ?FieldDto $fieldDto, EntityDto $entityDto): void
{
if ('today' === $filterDataDto->getValue()) {
$queryBuilder->andWhere(sprintf('%s.%s = :today', $filterDataDto->getEntityAlias(), $filterDataDto->getProperty()))
->setParameter('today', (new \DateTime('today'))->format('Y-m-d'));
}
// ...
}
}
然后,创建关联的表单类型,例如,渲染一个带有某些预定义值的 <select>
小部件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
// src/Form/Type/Admin/DateCalendarFilterType.php
namespace App\Form\Type\Admin;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\OptionsResolver\OptionsResolver;
class DateCalendarFilterType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'choices' => [
'Today' => 'today',
'This month' => 'this_month',
// ...
],
]);
}
public function getParent()
{
return ChoiceType::class;
}
}
你现在可以在你的任何仪表盘和 CRUD 控制器中使用此自定义过滤器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
namespace App\Controller\Admin;
use App\Admin\Filter\DateCalendarFilter;
use EasyCorp\Bundle\EasyAdminBundle\Config\Filters;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Filter\BooleanFilter;
class UserCrudController extends AbstractCrudController
{
// ...
public function configureFilters(Filters $filters): Filters
{
return $filters
// ...
->add(DateCalendarFilter::new('signupDate'))
;
}
}
未映射的过滤器
默认情况下,每个过滤器都必须与实体的属性关联。但是,有时你需要按相关实体的属性进行过滤(例如,一个 order
与一个 customer
关联,并且你想按 customer
的 country
属性过滤订单)。在这些情况下,将过滤器中的 mapped
选项设置为 false
,否则你将看到异常
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
namespace App\Controller\Admin;
use App\Admin\Filter\CustomerCountryFilter;
use EasyCorp\Bundle\EasyAdminBundle\Config\Filters;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Filter\BooleanFilter;
class OrderCrudController extends AbstractCrudController
{
// ...
public function configureFilters(Filters $filters): Filters
{
return $filters
// 'country' doesn't exist as a property of 'Order' so it's
// defined as 'not mapped' to avoid errors
->add(CustomerCountryFilter::new('country')->setFormTypeOption('mapped', false))
;
}
}
这项工作,包括代码示例,已获得 Creative Commons BY-SA 3.0 许可协议的许可。