跳到内容

过滤器

编辑此页

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 关联,并且你想按 customercountry 属性过滤订单)。在这些情况下,将过滤器中的 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 许可协议的许可。
目录
    版本