SYMFONY 自定义约束 ->将变量传递给自定义 CONSTRAINT/绑定到表单字段的 CONSTRAINT 如何可以在 ANNOTATION 中 OVERRIDE CONSTRAINT [英] SYMFONY custom CONSTRAINT -> Pass variable to a custom CONSTRAINT / How CONSTRAINT binded to a form field can OVERRIDE CONSTRAINT in ANNOTATION

查看:54
本文介绍了SYMFONY 自定义约束 ->将变量传递给自定义 CONSTRAINT/绑定到表单字段的 CONSTRAINT 如何可以在 ANNOTATION 中 OVERRIDE CONSTRAINT的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标:我在 SYMFONY 中构建了一个自定义约束,我需要将一个变量传递给该约束.

My goal: I built a custom constraint in SYMFONY, I needed to pass a variable to that constraint.

上下文:约束检查一个值在数据库中是否唯一,如果不是,它会引发一个 CONSTRAINT 警报.当 FORM 用于在 DB 中创建新元组时,这可以正常工作 但如果它是一个编辑,它会引发一个异常,应该通过检查该值是否已经存在,是否存在正在编辑的元组 ID 来绕过该异常.

The context: The constraint do a check if a value is unique in the DB, if it is not, it raises a CONSTRAINT alert. That works alright when the FORM is used to create a new tuple in the DB but if it is an edit it raises an exception which should be bypass by checking that the value already existing, exists for the tuple Id being edited.

因此我需要将正在编辑的元组的 ID 传递给我的约束检查.

Hence I needed to pass the Id of the tuple being edited to my constraint check.

起初我在我的实体中实现了我的自定义约束:

At first I implemented my custom constraint in my entity:

class MyEntity{

    /**
    * @MyBundleAssert\CheckValueAlreadyInDB(
    *     message = "already_exists_in_db",
    *     fieldToSearch = "my_value",
    *     tableToSearch = "my_table"
    *)
    */
    private myValue;

} 

正如人们所看到的,我没有找到一种方法来实现一种使用带有 ANNOTATION 的约束来传递 VARIABLE 的方法.通过搜索,我明白我可以通过使用我的自定义约束类的 __construct() 来做到这一点:

As one can see, I did not find a way to implement a way to pass a VARIABLE using the constraint with ANNOTATION. By searching, I understood I could do that by using the __construct() of my custom constraint class:

/**
 * @Annotation
 */
class CheckValueAlreadyInDB extends Constraint{
public $message;
public $fieldToSearch;
public $tableToSearch;
public $idToCheck;
public $idToCheckFieldName;

public function __construct($options){
    if(count($options)>0){
        $this->idToCheck = $options['idToCheck'];
        $this->idToCheckFieldName = $options['idToCheckFieldName'];
        $this->fieldToSearch = $options['fieldToSearch'];
        $this->tableToSearch = $options['tableToSearch'];
        $this->message = $options['message'];
    }
}

public function validatedBy()
{
    return 'validator_check_value_already_in_db';
}
}

而且,链接到它的 ConstraintValidator 扩展类:

And, the ConstraintValidator extended class linked to it:

class CheckValueAlreadyInDBValidator extends ConstraintValidator
{
    private $con;

    public function __construct($con){
        $this->con = $con;
    }

    public function validate($value, Constraint $constraint)
    {
        ////My stuff to get a record from the DB////
        $sel = new PdoSelect($this->con);
        $search = $sel->returnRecordsInTableForSpecificKey([$constraint->fieldToSearch],[$value],  $constraint->tableToSearch,false);
       //////////////////////////////////////////////

        $sameId = false;
        if($constraint->idToCheck!==null){
            $idToCheckInRetrieveRecord = $search->{$constraint->idToCheckFieldName};            
            $sameId = ($idToCheckInRetrieveRecord==$constraint->idToCheck)?true:false;
        }

        if($search!=null&&!$sameId){
            $this->context->buildViolation($constraint->message)
                ->setParameter('%string%', $value)
                ->addViolation();
        }
    }
}

有服务:

validator.unique.check_value_already_in_db:
    class: MyBundle\Form\CustomConstraints\CheckValueAlreadyInDBValidator
    arguments: ['@doctrine.dbal.default_connection']
    tags:
        - { name: validator.constraint_validator, alias: validator_check_value_already_in_db }

我为有关 myValue 的字段创建了 FORM(AbstractType 扩展类),我确实编辑了 constraints 属性.

I my FORM (AbstractType extended class) for the field regarding myValue, I did edit the constraints attribute.

class MyEntityType extends AbstractType {     
public function buildForm(FormBuilderInterface $builder, array $options)
      {

    ....
        $builder->add('myValue',****Type::class,array(
          'constraints' => array(
              new CheckValueAlreadyInDB(array(
                'idToCheck'=>$options['data']->getId(),
                'idToCheckFieldName'=>'id',
                'fieldToSearch'=>'my_value',
                'tableToSearch'=>'my_table',
                'message' => "value_already_exists_in_db"))
            )
          ));

    ...
    }
}

我认为 buildForm() 中定义的 CONSTRAINT 将覆盖 MyEntity 类的 * @MyBundleAssert\CheckValueAlreadyInDB(..) 中定义的约束(应该是默认行为).但它没有!我必须删除 MyEntity 上方的 ANNOTATION 才能使约束按照 buildForm() 中的定义工作.

I thought that the CONSTRAINT defined in the buildForm() would override the one defined in the * @MyBundleAssert\CheckValueAlreadyInDB(..) of MyEntity class (which should be the default behaviour). But It did not! I had to delete the ANNOTATION above MyEntity to make the constraint work as defined in the buildForm().

有谁知道是否有一个设置可以允许在 buildForm() 中有一个约束覆盖一个作为 MyEntity 中的 ANNOTATION 存在的约束,但仍然让 MyEntity 中的字段上方的 ANNOTATION 为默认行为?或者有没有办法将 VARIABLE 传递给 ANNOTATIONS?

Does anyone know if there is a setting that could permit to have a constraint in a buildForm() overriding one existing as an ANNOTATION in MyEntity, but still let the ANNOTATION above a field in MyEntity be the default behavior? Or is there is a way to pass VARIABLE to ANNOTATIONS?

推荐答案

我找到了解决方案.

我的错误是尝试在类 MyEntityType 中使用约束扩展 AbstractType:

My mistake was to try to use constraints in class MyEntityType extends AbstractType:

 $builder->add('myValue',****Type::class,array(
  'constraints' => array(
      new CheckValueAlreadyInDB(array(
        'idToCheck'=>$options['data']->getId(),
        'idToCheckFieldName'=>'id',
        'fieldToSearch'=>'my_value',
        'tableToSearch'=>'my_table',
        'message' => "value_already_exists_in_db"))
    )
  ));

更新:

请勿在此处使用

看看 class-constraint-validator 文档中的部分.

Have a look at class-constraint-validator section in the doc.

在验证器必须执行其检查的实体类之上而不是实体类的一个属性之上实现 ConstraintValidator 扩展类.这样就可以访问实体的其他属性,并将其用作 ConstraintValidator 扩展类中的条件.

Implement the ConstraintValidator extended class above the class of the Entity where the validator has to execute its check and not above one attribute of the Entity class. That way one can have access to other attributes of the entity and use it as conditionals in the ConstraintValidator extended class.

这篇关于SYMFONY 自定义约束 ->将变量传递给自定义 CONSTRAINT/绑定到表单字段的 CONSTRAINT 如何可以在 ANNOTATION 中 OVERRIDE CONSTRAINT的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆