4. Inline Validation¶
The inline validation is about delegating model validation to a
dedicated service. The current validation implementation built in the
Symfony framework is very powerful as it allows to declare validation on
a : class, field and getter. However, these declarations can take a
while to code for complex rules. As rules must be a set of a
Constraint
and a Validator
instances.
The inline validation tries to provide a nice solution by introducing an ErrorElement
object. The object can be used to check assertions against the model:
$errorElement
->with('settings.url')
->assertNotNull([])
->assertNotBlank()
->end()
->with('settings.title')
->assertNotNull([])
->assertNotBlank()
// for minimum length constraint
->assertLength(['min' => 50])
// for maximum length constraint
->assertLength(['max' => 100])
->addViolation('ho yeah!')
->end();
// ...
if (/* complex rules */) {
$errorElement
->with('value')
->addViolation('Fail to check the complex rules')
->end();
}
// ...
/* Specify the translation domain */
$errorElement
->with('value')
->addViolation('translation_key_with_{var}', ['%var%' => 'value'], null, 'translation_domain')
->end();
// ...
/* conditional validation */
if ($this->getSubject()->getState() == Post::STATUS_ONLINE) {
$errorElement
->with('enabled')
->assertNotNull()
->assertTrue()
->end();
}
Note
This solution relies on the validator component so validation defined by the validator component will be used.
Tip
You can also use $errorElement->addConstraint(new \Symfony\Component\Validator\Constraints\NotBlank())
instead of calling assertNotBlank()
.
You can also use $errorElement->addConstraint(new \Symfony\Component\Validator\Constraints\Length(['min'=>5, 'max'=>100])
instead of calling assertLength()
.
4.1. Using this Validator¶
Add the InlineConstraint
class constraint to your bundle’s validation configuration:
- YAML
1 2 3 4 5 6 7
# src/Application/Sonata/PageBundle/Resources/config/validation.yaml Application\Sonata\PageBundle\Entity\Block: constraints: - Sonata\Form\Validator\Constraints\InlineConstraint: service: sonata.page.cms.page method: validateBlock
- XML
1 2 3 4 5 6 7 8 9 10 11 12 13 14
<!-- src/Application/Sonata/PageBundle/Resources/config/validation.xml --> <?xml version="1.0" ?> <constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd"> <class name="Application\Sonata\PageBundle\Entity\Block"> <constraint name="Sonata\Form\Validator\Constraints\InlineConstraint"> <option name="service">sonata.page.cms.page</option> <option name="method">validateBlock</option> </constraint> </class> </constraint-mapping>
There are two important options:
service
: the service where the validation method is definedmethod
: the service’s method to call
Note
If the service
or method
is not a string, you will need to
re-attach the validation on each request. Set the
serializingWarning
option to true
once it is done.
The method must accept two arguments:
ErrorElement
: the instance where assertion can be checkedvalue
: the object instance
4.2. Example from the SonataPageBundle
¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | namespace Sonata\PageBundle\Block;
use Sonata\PageBundle\Model\PageInterface;
use Sonata\Form\Validator\ErrorElement;
use Sonata\BlockBundle\Block\BaseBlockService;
use Sonata\BlockBundle\Model\BlockInterface;
class RssBlockService extends BaseBlockService
{
// ...
public function validateBlock(ErrorElement $errorElement, BlockInterface $block)
{
$errorElement
->with('settings.url')
->assertNotNull([])
->assertNotBlank()
->end()
->with('settings.title')
->assertNotNull([])
->assertNotBlank()
// for minimum length constraint
->assertLength(['min' => 50])
// for maximum length constraint
->assertLength(['max' => 100])
->addViolation('ho yeah!')
->end();
}
}
|