Reputation:
I created my custom constraint validator:
class CustomConstraint extends Constraint
{
public $message = '';
}
class CustomConstraintValidator extends ConstraintValidator
{
public function validate($value, Constraint $constraint)
{
exit($this->context->getObject()); // returns null
}
}
In docs it is stated that:
Returns the currently validated object.
, but for me it returns NULL
instead.
P.S. I do not want to assign this constraint to Entity, only to certain forms or fields.
My form property which is validated:
->add('rejectReasons', null, array(
'property' => 'name',
'multiple' => true,
'constraints' => array(
new CustomConstraint(array(
'message' => 'Application can not be refused.'
)),
)
));
Property in entity:
/**
* @ORM\ManyToMany(targetEntity="RejectReason")
* @ORM\JoinTable(name="relationship_application_reject_reasons",
* joinColumns={@ORM\JoinColumn(name="application_id", referencedColumnName="id", onDelete="CASCADE")},
* inverseJoinColumns={@ORM\JoinColumn(name="reject_reason_id", referencedColumnName="id")}
* )
*/
private $rejectReasons;
UPDATE
I tried putting constraint on other string property, I still get NULL
.
Upvotes: 3
Views: 6857
Reputation: 4541
The answer is simple. Write :
this->context->getRoot()->getData()
and u have the object.
Upvotes: 1
Reputation: 864
For those making form validation using dependencies itself this can help.
I assume that the Symfony version is 3.4 or 4.1 and you have symfony/form
on your project.
The best way to deal with Symfony Form Validators with some kind of dependency are using CustomValidators
Above is a example that I use to work with them.
Supposed that we have an Entity like
// src/Entity/myEntity.php
namespace App\Entity;
...
class myEntity
{
private $id;
private $name; // string, required
private $canDrive; // bool, not required (default=false)
private $driveLicense; // string, not required (default = null)
public function __construct()
{
$this->canDrive = false;
}
// getters and setters
}
We don't need to populate $driveLicense
(cause the attribute its not mandatory), but if $canDrive
change from false
to true
, now $driveLicense
must have a value.
$driveLicense
is $canDrive
dependent.
To build a form for that and validate $driveLicense
correctly on the FormType (the best practice) we need to build a CustomConstraintValidator.
// src/Validator/Constraints/CanDrive.php
namespace App\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
class CanDrive extends Constraint
{
public $message = 'invalid_candrive_args'; // I like translators :D
}
Translator file - optional
//src/translators/validators.en.yaml //
invalid_candrive_args: When "{{ candrivelabel }} " field is checked you must fill "{{ drivelicenselabel }}"
The validator
// src/Validator/Constraints/CanDriveValidator.php
namespace App\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class CanDriveValidator extends ConstraintValidator
{
/**
* Checks if the passed value is valid.
*
* @param mixed $value The value that should be validated
* @param Constraint $constraint The constraint for the validation
*/
public function validate($value, Constraint $constraint)
{
$canDriveField = $this->context->getObject(); // the Field using this validator
$form = $canDriveField->getParent(); // the formType where the Field reside
$myEntity = $form->getData(); // The Entity mapped by formType
if ($myEntity->getCanDrive() == true && $myEntity->getDriveLicense() == null) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ candrivelabel }}', 'Can Drive')
->setParameter('{{ drivelicenselabel }}', 'Drive License')
->addViolation();
}
}
}
The form myEntityType
//src/Form/myEntityType.php
namespace App\Form;
use App\Entity\myEntity;
use App\Validator\Constraints\CanDrive;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class myEntityType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name')
->add('canDrive', CheckBoxType::class, [
'required' => false,
'constraints' => array(new canDrive()),
]
)
->add('driveLicense', TextType::class, ['required' => false])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(['data_class' => myEntity::class]);
}
}
Now, when use call isValid()
method of myEntityType form and the canDrive field was checked and driveLicense is blank, a Violation will be fired on canDrive field. If canDrive is set to false (not checked, not submitted), nothing happens and form will be valid even when driveLicense is blank.
Upvotes: 2
Reputation: 39380
If you are develep a Class Constraint Validator remember to add the getTargets method as example:
public function getTargets()
{
return self::CLASS_CONSTRAINT;
}
As described here in the doc
Upvotes: 0
Reputation: 1379
Look at ExecutionContextInterface it says that:
getObject() Returns the currently validated object.
If the validator is currently validating a class constraint, the object of that class is returned. If it is a validating a property or getter constraint, the object that the property/getter belongs to is returned.
In other cases, null is returned.
So as you can see, you have to assign to a class or a property or getter. Otherwise you will get null
.
Upvotes: 6