跳到内容

Callback

编辑此页

Callback 约束的目的是创建完全自定义的验证规则,并将任何验证错误分配给对象上的特定字段。如果将验证与表单一起使用,这意味着您可以将自定义错误显示在它们适用的字段旁边,而不是在表单顶部显示自定义错误。

此过程通过指定一个或多个 callback 方法来实现,每个方法将在验证过程中被调用。这些方法中的每一个都可以执行任何操作,包括创建和分配验证错误。

注意

callback 方法本身不会失败或返回任何值。相反,正如您将在示例中看到的那样,callback 方法能够直接添加验证器“违规”。

适用于 属性/方法
Callback
验证器 CallbackValidator

配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// src/Entity/Author.php
namespace App\Entity;

use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;

class Author
{
    #[Assert\Callback]
    public function validate(ExecutionContextInterface $context, mixed $payload): void
    {
        // ...
    }
}

Callback 方法

callback 方法被传递一个特殊的 ExecutionContextInterface 对象。您可以在此对象上直接设置“违规”,并确定这些错误应归于哪个字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// ...
use Symfony\Component\Validator\Context\ExecutionContextInterface;

class Author
{
    // ...
    private string $firstName;

    public function validate(ExecutionContextInterface $context, mixed $payload): void
    {
        // somehow you have an array of "fake names"
        $fakeNames = [/* ... */];

        // check if the name is actually a fake name
        if (in_array($this->getFirstName(), $fakeNames)) {
            $context->buildViolation('This name sounds totally fake!')
                ->atPath('firstName')
                ->addViolation();
        }
    }
}

静态 Callback

您还可以将约束与静态方法一起使用。由于静态方法无法访问对象实例,因此它们将对象作为第一个参数接收

1
2
3
4
5
6
7
8
9
10
11
12
13
public static function validate(mixed $value, ExecutionContextInterface $context, mixed $payload): void
{
    // somehow you have an array of "fake names"
    $fakeNames = [/* ... */];

    // check if the name is actually a fake name
    if (in_array($value->getFirstName(), $fakeNames)) {
        $context->buildViolation('This name sounds totally fake!')
            ->atPath('firstName')
            ->addViolation()
        ;
    }
}

外部 Callback 和闭包

如果您想执行不在已验证对象类中的静态 callback 方法,您可以配置约束以调用 PHP 的 call_user_func 函数支持的数组可调用方法。假设您的验证函数是 Acme\Validator::validate()

1
2
3
4
5
6
7
8
9
10
11
namespace Acme;

use Symfony\Component\Validator\Context\ExecutionContextInterface;

class Validator
{
    public static function validate(mixed $value, ExecutionContextInterface $context, mixed $payload): void
    {
        // ...
    }
}

然后,您可以使用以下配置来调用此验证器

1
2
3
4
5
6
7
8
9
10
// src/Entity/Author.php
namespace App\Entity;

use Acme\Validator;
use Symfony\Component\Validator\Constraints as Assert;

#[Assert\Callback([Validator::class, 'validate'])]
class Author
{
}

注意

Callback 约束支持全局 callback 函数,也不可能将全局函数或服务方法指定为 callback。要使用服务进行验证,您应该创建一个自定义验证约束并将该新约束添加到您的类中。

通过 PHP 配置约束时,您还可以将闭包传递给 Callback 约束的构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// src/Entity/Author.php
namespace App\Entity;

use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Mapping\ClassMetadata;

class Author
{
    public static function loadValidatorMetadata(ClassMetadata $metadata): void
    {
        $callback = function (mixed $value, ExecutionContextInterface $context, mixed $payload): void {
            // ...
        };

        $metadata->addConstraint(new Assert\Callback($callback));
    }
}

警告

Closure 与属性配置一起使用将禁用该类/属性/方法的属性缓存,因为 Closure 无法缓存。为了获得最佳性能,建议使用静态 callback 方法。

选项

callback

类型: stringarrayClosure [默认选项]

callback 选项接受三种不同的格式来指定 callback 方法

  • 一个 string,其中包含具体方法或静态方法的名称;
  • 格式为 ['<Class>', '<method>'] 的数组可调用方法;
  • 一个闭包。

具体 callback 接收 ExecutionContextInterface 实例作为第一个参数,payload 选项作为第二个参数。

静态或闭包 callback 接收已验证的对象作为第一个参数,ExecutionContextInterface 实例作为第二个参数,payload 选项作为第三个参数。

groups

类型: array | string 默认值: null

它定义此约束的验证组。阅读更多关于验证组的信息。

payload

类型: mixed 默认值: null

此选项可用于将任意特定于域的数据附加到约束。配置的 payload 不会被 Validator 组件使用,但其处理完全取决于您。

例如,您可能希望使用多个错误级别,以便根据错误严重程度在前端以不同方式呈现失败的约束。

本作品,包括代码示例,根据 Creative Commons BY-SA 3.0 许可协议获得许可。
目录
    版本