conditional_validation.rst 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. Inline Validation
  2. =================
  3. The inline validation is about delegating model validation to a dedicated service.
  4. The current validation implementation built in the Symfony2 framework is very powerful
  5. as it allows to declare validation on a : class, field and getter. However these declarations
  6. can take a while to code for complex rules. As rules must be a set of a ``Constraint``
  7. and a ``Validator`` instances.
  8. The inline validation tries to provide a nice solution by introducing an ``ErrorElement``
  9. object. The object can be used to check assertions against the model :
  10. .. code-block:: php
  11. <?php
  12. $errorElement
  13. ->with('settings.url')
  14. ->assertNotNull(array())
  15. ->assertNotBlank()
  16. ->end()
  17. ->with('settings.title')
  18. ->assertNotNull(array())
  19. ->assertNotBlank()
  20. // for minimum length constraint
  21. ->assertLength(array('min' => 50))
  22. // for maximum length constraint
  23. ->assertLength(array('max' => 100))
  24. ->addViolation('ho yeah!')
  25. ->end();
  26. if (/* complex rules */) {
  27. $errorElement->with('value')->addViolation('Fail to check the complex rules')->end()
  28. }
  29. /* conditional validation */
  30. if ($this->getSubject()->getState() == Post::STATUS_ONLINE) {
  31. $errorElement
  32. ->with('enabled')
  33. ->assertNotNull()
  34. ->assertTrue()
  35. ->end();
  36. }
  37. .. note::
  38. This solution relies on the validator component so validation defined through
  39. the validator component will be used.
  40. .. tip::
  41. You can also use ``$errorElement->addConstraint(new \Symfony\Component\Validator\Constraints\NotBlank())``
  42. instead of calling assertNotBlank().
  43. You can also use ``$errorElement->addConstraint(new \Symfony\Component\Validator\Constraints\Length(array('min'=>5, 'max'=>100))``
  44. instead of calling assertLength().
  45. Using this validator
  46. --------------------
  47. Add the ``InlineConstraint`` class constraint to your bundle's validation configuration, for example:
  48. .. configuration-block::
  49. .. code-block:: xml
  50. <!-- src/Application/Sonata/PageBundle/Resources/config/validation.xml -->
  51. <?xml version="1.0" ?>
  52. <constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
  53. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  54. xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">
  55. <class name="Application\Sonata\PageBundle\Entity\Block">
  56. <constraint name="Sonata\AdminBundle\Validator\Constraints\InlineConstraint">
  57. <option name="service">sonata.page.cms.page</option>
  58. <option name="method">validateBlock</option>
  59. </constraint>
  60. </class>
  61. </constraint-mapping>
  62. .. code-block:: yaml
  63. # src/Application/Sonata/PageBundle/Resources/config/validation.yml
  64. Application\Sonata\PageBundle\Entity\Block:
  65. constraints:
  66. - Sonata\AdminBundle\Validator\Constraints\InlineConstraint:
  67. service: sonata.page.cms.page
  68. method: validateBlock
  69. There are two important options:
  70. - ``service``: the service where the validation method is defined
  71. - ``method``: the service's method to call
  72. The method must accept two arguments:
  73. - ``ErrorElement``: the instance where assertion can be checked
  74. - ``value``: the object instance
  75. Example from the ``SonataPageBundle``
  76. -------------------------------------
  77. .. code-block:: php
  78. <?php
  79. namespace Sonata\PageBundle\Block;
  80. use Sonata\PageBundle\Model\PageInterface;
  81. use Sonata\AdminBundle\Validator\ErrorElement;
  82. use Sonata\BlockBundle\Block\BaseBlockService;
  83. use Sonata\BlockBundle\Model\BlockInterface;
  84. class RssBlockService extends BaseBlockService
  85. {
  86. // ... code removed for simplification
  87. public function validateBlock(ErrorElement $errorElement, BlockInterface $block)
  88. {
  89. $errorElement
  90. ->with('settings.url')
  91. ->assertNotNull(array())
  92. ->assertNotBlank()
  93. ->end()
  94. ->with('settings.title')
  95. ->assertNotNull(array())
  96. ->assertNotBlank()
  97. // for minimum length constraint
  98. ->assertLength(array('min' => 50))
  99. // for maximum length constraint
  100. ->assertLength(array('max' => 100))
  101. ->addViolation('ho yeah!')
  102. ->end();
  103. }
  104. }
  105. Using the Admin class
  106. ---------------------
  107. This feature is deprecated and will be removed on the 2.2 branch.
  108. The above examples show how to delegate validation to a service. For completeness, it's worth remembering that
  109. the ``Admin`` class itself contains an empty ``validate`` method. This is automatically called, so you can override it in your own admin class:
  110. .. code-block:: php
  111. // add this to your existing use statements
  112. use Sonata\AdminBundle\Validator\ErrorElement;
  113. class MyAdmin extends Admin
  114. {
  115. // add this method
  116. public function validate(ErrorElement $errorElement, $object)
  117. {
  118. $errorElement
  119. ->with('name')
  120. ->assertLength(array('max' => 32))
  121. ->end()
  122. ;
  123. }
  124. Troubleshooting
  125. ---------------
  126. Make sure your validator method is being called. If in doubt, try throwing an exception:
  127. .. code-block:: php
  128. public function validate(ErrorElement $errorElement, $object)
  129. {
  130. throw new \Exception(__METHOD__);
  131. }
  132. There should not be any validation_groups defined for the form. If you have code like the example below in
  133. your ``Admin`` class, remove the 'validation_groups' entry, the whole $formOptions property or set validation_groups
  134. to an empty array:
  135. .. code-block:: php
  136. protected $formOptions = array(
  137. 'validation_groups' => array()
  138. );