Mein Ziel: Ich baute eine benutzerdefinierte Einschränkung in SYMFONY, ich musste eine Variable an diese Einschränkung übergeben.SYMFONY benutzerdefinierte CONSTRAINT -> Variable an einen benutzerdefinierten CONSTRAINT übergeben/Wie CONSTRAINT an ein Formularfeld gebunden kann CONSTRAINT in ANNOTATION ÜBERNEHMEN
Der Kontext: Die Einschränkung überprüft, ob ein Wert in der DB eindeutig ist. Ist dies nicht der Fall, wird eine CONSTRAINT-Warnung ausgelöst. Das funktioniert gut, wenn die FORM verwendet wird, um ein neues Tupel in der DB zu erstellen, aber wenn es eine Bearbeitung ist, löst es eine Ausnahme aus, die umgangen werden soll, indem der bereits vorhandene Wert für die Tupel-ID bearbeitet wird.
Daher musste ich die ID des Tupels, das bearbeitet wurde, an meine Constraint-Prüfung übergeben.
Zuerst implementiert ich meine benutzerdefinierte Einschränkung in meiner Einheit:
class MyEntity{
/**
* @MyBundleAssert\CheckValueAlreadyInDB(
* message = "already_exists_in_db",
* fieldToSearch = "my_value",
* tableToSearch = "my_table"
*)
*/
private myValue;
}
Wie man sehen kann, kann ich nicht einen Weg, einen Weg zu implementieren passieren eine Variable mit der Einschränkung mit ANNOTATION gefunden hat. Durch die Suche, verstand ich, was ich tun konnte, dass durch die __construct()
meine benutzerdefinierte Constraint-Klasse:
/**
* @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';
}
}
Und der ConstraintValidator erweiterte Klasse mit ihm verbunden:
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();
}
}
}
Mit 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 }
Ich meine FORM (AbstractType erweiterte Klasse) für das Feld in Bezug auf myValue, habe ich das constraints
Attribut bearbeiten.
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"))
)
));
...
}
}
Ich dachte, dass die Einschränkung in der buildForm()
definiert die man in der * @MyBundleAssert\CheckValueAlreadyInDB(..)
von MyEntity Klasse definiert würde außer Kraft setzen (die das Standardverhalten sein sollte). Aber es hat nicht! Ich musste die ANNOTATION über MyEntity löschen, damit die Einschränkung wie in buildForm()
definiert funktioniert.
Weiß jemand, ob es eine Einstellung, die eine Einschränkung in einem buildForm()
zwingenden einem bestehenden als ANNOTATION in MyEntity haben erlauben könnte, aber immer noch die ANNOTATION über ein Feld in MyEntity läßt das Standardverhalten sein? Oder gibt es eine Möglichkeit, VARIABLE an ANNOTATIONEN zu übergeben?