SYMFONY 自定义 CONSTRAINT -> 将变量传递给自定义 CONSTRAINT / 绑定到表单字段的 CONSTRAINT 如何覆盖 ANNOTATION 中的 CONSTRAINT
SYMFONY custom CONSTRAINT -> Pass variable to a custom CONSTRAINT / How CONSTRAINT binded to a form field can OVERRIDE CONSTRAINT in ANNOTATION
我的目标:我在 SYMFONY 中构建了一个自定义约束,我需要将一个变量传递给该约束。
上下文:约束检查数据库中的值是否唯一,如果不是,它会引发 CONSTRAINT 警报。当 FORM 用于在数据库中创建一个新元组时,这工作正常 但如果它是一个编辑,它会引发一个异常,应该通过检查已经存在的值来绕过该异常,存在于正在编辑的元组 ID .
因此我需要将正在编辑的元组的 ID 传递给我的约束检查。
起初我在我的实体中实现了我的自定义约束:
class MyEntity{
/**
* @MyBundleAssert\CheckValueAlreadyInDB(
* message = "already_exists_in_db",
* fieldToSearch = "my_value",
* tableToSearch = "my_table"
*)
*/
private myValue;
}
如您所见,我没有找到一种方法来实现使用带注释的约束来传递变量的方法。通过搜索,我知道我可以通过使用自定义约束 class 的 __construct()
来做到这一点:
/**
* @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 扩展 class 链接到它:
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 }
我的 FORM(AbstractType extended class)关于 myValue 的字段,我确实编辑了 constraints
属性。
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()
中定义的约束会覆盖 MyEntity class 的 * @MyBundleAssert\CheckValueAlreadyInDB(..)
中定义的约束(这应该是默认行为)。但它没有! 我不得不删除 MyEntity 上方的注释以使约束按照 buildForm()
.
中定义的方式工作
有谁知道是否有一个设置可以允许 buildForm()
中的约束覆盖 MyEntity 中作为 ANNOTATION 存在的约束,但仍然让 MyEntity 中字段上方的 ANNOTATION 成为默认行为?或者有没有办法将 VARIABLE 传递给 ANNOTATIONS?
我找到了解决方案。
我的错误是试图在 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 部分。
在验证器必须执行其检查的实体 class 之上实施 ConstraintValidator
扩展 class,而不是在实体 class 的一个属性之上。这样就可以访问实体的其他属性并将其用作 ConstraintValidator
扩展 class.
中的条件
我的目标:我在 SYMFONY 中构建了一个自定义约束,我需要将一个变量传递给该约束。
上下文:约束检查数据库中的值是否唯一,如果不是,它会引发 CONSTRAINT 警报。当 FORM 用于在数据库中创建一个新元组时,这工作正常 但如果它是一个编辑,它会引发一个异常,应该通过检查已经存在的值来绕过该异常,存在于正在编辑的元组 ID .
因此我需要将正在编辑的元组的 ID 传递给我的约束检查。
起初我在我的实体中实现了我的自定义约束:
class MyEntity{
/**
* @MyBundleAssert\CheckValueAlreadyInDB(
* message = "already_exists_in_db",
* fieldToSearch = "my_value",
* tableToSearch = "my_table"
*)
*/
private myValue;
}
如您所见,我没有找到一种方法来实现使用带注释的约束来传递变量的方法。通过搜索,我知道我可以通过使用自定义约束 class 的 __construct()
来做到这一点:
/**
* @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 扩展 class 链接到它:
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 }
我的 FORM(AbstractType extended class)关于 myValue 的字段,我确实编辑了 constraints
属性。
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()
中定义的约束会覆盖 MyEntity class 的 * @MyBundleAssert\CheckValueAlreadyInDB(..)
中定义的约束(这应该是默认行为)。但它没有! 我不得不删除 MyEntity 上方的注释以使约束按照 buildForm()
.
有谁知道是否有一个设置可以允许 buildForm()
中的约束覆盖 MyEntity 中作为 ANNOTATION 存在的约束,但仍然让 MyEntity 中字段上方的 ANNOTATION 成为默认行为?或者有没有办法将 VARIABLE 传递给 ANNOTATIONS?
我找到了解决方案。
我的错误是试图在 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 部分。
在验证器必须执行其检查的实体 class 之上实施 ConstraintValidator
扩展 class,而不是在实体 class 的一个属性之上。这样就可以访问实体的其他属性并将其用作 ConstraintValidator
扩展 class.