I\'m creating a form in Symfony2. The form only contains one book
field which allows the user to choose between a list of Books
entities. I need to c
Thank you @JasonRoman, Your solution worked perfectly for me in Symfony 3.4.
I had an error in my Validator when I used :
$author = $this->constraint->getAuthor();
But it worked when I used this instead :
$author = $constraint->getAuthor();
Start by adding a setAuthor method to your constraint and then tweaking the validate method. The trick then is to determine the best place to call it.
It's not clear exactly how you are binding the validator to your book. Are you using validation.yml or doing something inside of the form?
Well, I'm not that familier with the Form/Validation component, but you can use a Hidden field with the name/id of the author and check if it's the same:
class MyFormType extends AbstractType
{
protected $author;
public function __construct(Author $author) {
$this->author = $author;
}
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('book', 'entity', array('class' => 'AcmeDemoBundle:Book', 'field' => 'title');
->add('author_name', 'hidden', array(
'data' => $this->author->getId(),
))
;
}
// ...
}
I finally figured it out, with the help from Cerad. To inject custom parameters that need to be accessed from the ConstraintValidator::validate()
method, you need to pass them as options in the Constraint
.
public class HasValidAuthorConstraint extends Constraint
{
protected $author;
public function __construct($options)
{
if($options['author'] and $options['author'] instanceof Author)
{
$this->author = $options['author'];
}
else
{
throw new MissingOptionException("...");
}
}
public function getAuthor()
{
return $this->author;
}
}
And, in the ConstraintValidator:
class HasValidAuthorConstraintValidator extends ConstraintValidator
{
private $entityManager;
public function __construct(EntityManager $entityManager) {
$this->entityManager = $entityManager;
}
public function validate($value, Constraint $constraint) {
$book = $this->entityManager->getRepository('book')->findOneById($value);
$author = $this->constraint->getAuthor();
if(!$book->isAuthor($author))
{
$this->context->addViolation(...);
}
}
}
Last but not least, you have to pass the parameter to the Validator:
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('book', 'entity', array(
'class' => 'AcmeDemoBundle:Book',
'field' => 'title',
'constraints' => array(
new HasValidAuthorConstraint(array(
'author' => $this->author
))
)
));
}
Accepted answer did not work for me using Symfony Framework version 2.1. This is how I solved it.
class CustomConstraint extends Constraint
{
public $dependency;
public $message = 'The error message.';
}
class CustomConstraintValidator extends ConstraintValidator
{
public function validate($value, Constraint $constraint)
{
if (!$constraint->dependency->allows($value)) {
$this->context->addViolation($constraint->message);
}
}
}
class CustomFormType extends AbstractType
{
private $dependency;
public function __construct(Dependency $dependency)
{
$this->dependency = $dependency;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('field', 'type', array(
'constraints' => array(
new CustomConstraint(array('dependency' => $this->dependency))
)
));
}
}