Symfony:如何在自定义约束中集成内置标准约束?
在Symfony自定义验证约束中集成内置Url约束的方法
当然可以不用在实体类上直接添加Url约束,直接把内置的Url验证逻辑集成到自定义约束里。之前调用Validator的validate方法没生效,大概率是没正确传递验证上下文或者参数,下面是两种可靠的实现方式:
方法一:直接复用内置UrlValidator
在自定义约束的Validator类中,注入内置的UrlValidator,然后在自定义验证逻辑里调用它的validate方法并传递当前上下文,这样内置约束的违规信息会自动合并到自定义约束的验证结果中。
自定义约束类
namespace App\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation */ class CustomUrl extends Constraint { public $message = "该URL不符合自定义规则"; public function validatedBy() { return static::class . 'Validator'; } }
对应的Validator实现
namespace App\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Url; use Symfony\Component\Validator\Constraints\UrlValidator; use Symfony\Component\Validator\ConstraintValidator; class CustomUrlValidator extends ConstraintValidator { private $urlValidator; public function __construct(UrlValidator $urlValidator) { $this->urlValidator = $urlValidator; } public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } // 先执行内置Url约束验证 $urlConstraint = new Url([ 'message' => '这不是一个有效的URL', 'protocols' => ['http', 'https'] // 可自定义Url约束的配置项 ]); $this->urlValidator->validate($value, $urlConstraint, $this->context); // 执行你的自定义验证逻辑 if (str_contains($value, 'forbidden.com')) { $this->context->buildViolation($constraint->message) ->setParameter('{{ value }}', $value) ->addViolation(); } } }
方法二:使用ValidatorInterface的validateValue方法
如果不想直接注入UrlValidator,也可以通过ValidatorInterface的validateValue方法执行内置Url约束,然后将返回的违规信息手动添加到当前上下文:
namespace App\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Url; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Validator\ValidatorInterface; class CustomUrlValidator extends ConstraintValidator { private $validator; public function __construct(ValidatorInterface $validator) { $this->validator = $validator; } public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } // 执行内置Url约束验证 $urlConstraint = new Url([ 'message' => 'URL格式无效' ]); $violations = $this->validator->validateValue($value, $urlConstraint); // 将内置约束的违规信息添加到当前上下文 foreach ($violations as $violation) { $this->context->buildViolation($violation->getMessage()) ->setParameters($violation->getParameters()) ->addViolation(); } // 自定义验证逻辑 if (strlen($value) > 255) { $this->context->buildViolation($constraint->message) ->setParameter('{{ value }}', $value) ->addViolation(); } } }
这两种方式都不需要在实体类上额外添加Url约束注解,所有验证逻辑都封装在自定义约束里,保持实体类的代码简洁。
内容的提问来源于stack exchange,提问作者Mulot
相关产品推荐
相关产品推荐

