Reputation: 25
I have Item entity class, and I must validate it. I have condition that price must be less than 1000. And if price is less than 5, and stock is less 10 it is wrong too. So for first condition I use LessThan Constraint, but what should I do for the second condition?
class Item {
/**
* @ORM\Column(type="float")
* @Assert\LessThan(self::ITEM_MAX_PRICE)
*/
private float $price;
/**
* @ORM\Column(type="integer")
*/
private int $stock;
}
How can I validate this both property's with second condition?
Upvotes: 1
Views: 2957
Reputation: 11
So, I think you need to look at this: https://medium.com/@gregurco.vlad/symfony-validation-trick-dependent-validation-eb48bc5e3d81
Upvotes: 0
Reputation: 49238
I would use a custom validator. Here's an example from one of my projects (3.4).
Three files:
<?php // src/AppBundle/Validator/Constraint/HasValidDimensions.php
namespace AppBundle\Validator\Constraint;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
*/
class HasValidDimensions extends Constraint
{
public $invalidWidth = 'Invalid width dimension.';
public $invalidHeight = 'Invalid height dimension.';
public function getTargets()
{
return self::CLASS_CONSTRAINT;
}
}
Note the use of CLASS_CONSTRAINT
. Now, the actual validator gives me access to the different parts (in this case it's a command validator):
<?php // src/AppBundle/Validator/Constraint/HasValidDimensionsValidator.php
namespace AppBundle\Validator\Constraint;
use AppBundle\Message\Command\PageTemplate\SetPageTemplateDimensions;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
/**
* @Annotation
*/
class HasValidDimensionsValidator extends ConstraintValidator
{
public function validate($setPageTemplateDimensions, Constraint $constraint): void
{
/* @var SetPageTemplateDimensions $setPageTemplateDimensions */
/* @var HasValidDimensions $constraint */
$pageTemplate = $setPageTemplateDimensions->getPageTemplate();
if ($setPageTemplateDimensions->getWidth() > $pageTemplate->getWidthReal()) {
$this->context
->buildViolation($constraint->invalidWidth)
->addViolation()
;
}
if ($setPageTemplateDimensions->getHeight() > $pageTemplate->getHeightReal()) {
$this->context
->buildViolation($constraint->invalidHeight)
->addViolation()
;
}
}
}
Then use the validator on the class:
<?php // src/AppBundle/Message/Command/PageTemplate/SetPageTemplateDimensions.php
namespace AppBundle\Message\Command\PageTemplate;
use AppBundle\Validator\Constraint as AppAssert;
/**
* @AppAssert\HasValidDimensions()
*/
class SetPageTemplateDimensions implements TenantOwnedInterface
{
Upvotes: 2
Reputation: 529
May be it is good and will be useful to use Group sequence. In this case first will be check is price is less than and only if the first is true will be checked another two assertion Something like that:
/**
* @Assert\GroupSequence({"Item", "Strict"})
*/
class Item
{
/**
* @ORM\Column(type="float")
* @Assert\LessThan(self::ITEM_MAX_PRICE)
* @Assert\GreaterThan(value=5, groups={"Strict"})
*/
private float $price;
/**
* @Assert\GreaterThan(value=10, groups={"Strict"})
* @ORM\Column(type="integer")
*/
private int $stock;
}
Upvotes: 0
Reputation: 1445
Unfortunately Symfony don't provide a build-in constraint to validate multiples properties between them (not so easy to do and maintain btw).
I suggest you to have a look to Callback constraint which allow flexibility to validate your entity.
But if your validation logic is growing I suggest you to do a custom validator. It's a service so you can inject services and test it easily.
Upvotes: 1