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

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

问题描述

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

上下文:约束检查数据库中的值是否唯一,如果不是,则引发CONSTRAINT警报。当FORM用于在DB 中创建新元组时,这种方式可以正常工作,但如果它是一个编辑,它会引发一个异常,该异常应通过检查已存在的值存在,因此我需要将正在编辑的元组的Id传递给我的约束检查。



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

  class MyEntity {

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


可以看出,我没有找到办法使用ANNOTATION约束实现一种传递VARIABLE的方法。通过搜索,我明白我可以通过使用自定义约束类的 __ construct()来实现这一点:

 / ** 
* @Annotation
* /
类CheckValueAlreadyInDB扩展约束{
public $ message;
public $ fieldToSearch;
public $ tableToSearch;
public $ idToCheck;
public $ idToCheckFieldName;
$ b $ 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扩展类链接到它:

  class CheckValueAlreadyInDBValidator extends ConstraintValidator 
{
private $ con;

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

public function validate($ value,Constraint $ constraint)
{
////我从DB获取记录的东西////
$ sel =新的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; ($ 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']
标签:
- {name:validator.constraint_validator,别名:validator_check_value_already_in_db}

我的my(AbstractType扩展类)是关于myValue的字段,我编辑了约束属性。

  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'] - > get Id(),
'idToCheckFieldName'=>'id',
'fieldToSearch'=>'my_value',
'tableToSearch'=>'my_table',
'message'=> value_already_exists_in_db))

));

...
}
}

我认为 buildForm()中定义的CONSTRAINT会覆盖 * @ MyBundleAssert \ CheckValueAlreadyInDB(..)(这应该是默认行为)。但它没有! 我必须删除上面的MyEntity上的ANNOTATION,以使约束在 buildForm()中定义。



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

解决方案

我找到了解决方案。



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

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

));

请勿在此使用 $ b

查看班级-constraint-validator 部分。

实现上面的 ConstraintValidator 扩展类验证者必须执行其检查并且不超过实体类的一个属性的实体的类。这样,人们可以访问实体的其他属性,并将它用作 ConstraintValidator 扩展类中的条件。


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

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.

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;

} 

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';
}
}

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();
        }
    }
}

With service:

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 }

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"))
            )
          ));

    ...
    }
}

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().

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?

解决方案

I found the solution.

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"))
    )
  ));

DON'T USE IT HERE

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

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 /绑定到表单字段的CONSTRAINT如何在注释中取代约束的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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