Symfony2/Doctrine - 需要访问数据库的验证约束

Daw*_*hia 3 doctrine symfony doctrine-orm

我有一个实体ArticlePattern,它有一个属性pattern(字符串).我需要访问数据库以检查模式是否正确.所以我想定义一个方法ArticlePattern::isPatternValid()并添加一个约束(使用Doctrine的注释),该约束将在Validator对象验证期间检查isPatternValid是否为true.

从我在这里和那里读到的,使一个实体依赖于服务容器并不是一个好主意,这意味着我无法从ArticlePattern :: isPatternValid()内部访问doctrine服务.

那么如何制作需要访问数据库的自定义验证约束呢?你是如何处理这种情况的,我认为看到很多关于从实体类访问服务容器的问题很常见.

编辑:

好的,谢谢大家,所以答案是自定义验证约束

Cro*_*zin 5

验证器对象可以是:

  • 一个简单的对象,根本没有与框架环境的连接.
  • 一个服务(在依赖注入容器的上下文中),只要它有必要就可以做absolutley任何事情Symfony\Component\Validator\ConstraintValidatorInterface

那么你有什么要做的?

  1. 定义一个简单的约束
  2. 覆盖validatedBy()方法返回验证器"name"(return 'my_validator';)
  3. 在DIC中定义一个简单的服务:

    <service id="project.validator.my" class="Project\Constraints\MyValidator">
        <!-- service definition here -->
    
        <!-- the service has to be tagged -->
        <tag name="validator.constraint_validator" alias="my_validator" />
    </service>
    
    Run Code Online (Sandbox Code Playgroud)

编辑

您已经询问了多个属性验证.在这种情况下,您可以创建与对象相关的验证器,而不是对象的属性.

  1. 在约束类中定义该约束的目标(属性/类):

    class MyConstraint ... {
        ...
    
        public function targets() {
            return self::CLASS_CONSTRAINT;
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 注释经过验证的类而不是属性:

    @Assert/MyConstraint(...)
    class MyClass {
        private $firstName;
        private $lastName;
    
        @Assert/Email
        private $email;
    
        ...
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 验证器本身看起来与验证属性的情况非常相似:

    class MyValidator extends ConstraintValidator {
        public function isValid($value, Constraint $constraint) {
            // $value is an object rather a property
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)