conditional_validation.rst 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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. class RssBlockService extends BaseBlockService
  83. {
  84. // ... code removed for simplification
  85. public function validateBlock(ErrorElement $errorElement, BlockInterface $block)
  86. {
  87. $errorElement
  88. ->with('settings.url')
  89. ->assertNotNull(array())
  90. ->assertNotBlank()
  91. ->end()
  92. ->with('settings.title')
  93. ->assertNotNull(array())
  94. ->assertNotBlank()
  95. // for minimum length constraint
  96. ->assertLength(array('min' => 50))
  97. // for maximum length constraint
  98. ->assertLength(array('max' => 100))
  99. ->addViolation('ho yeah!')
  100. ->end();
  101. }
  102. }
  103. Using the Admin class
  104. ---------------------
  105. This feature is deprecated and will be removed on the 2.2 branch.
  106. The above examples show how to delegate validation to a service. For completeness, it's worth remembering that
  107. the ``Admin`` class itself contains an empty ``validate`` method. This is automatically called, so you can override it in your own admin class:
  108. .. code-block:: php
  109. // add this to your existing use statements
  110. use Sonata\AdminBundle\Validator\ErrorElement;
  111. class MyAdmin extends Admin
  112. {
  113. // add this method
  114. public function validate(ErrorElement $errorElement, $object)
  115. {
  116. $errorElement
  117. ->with('name')
  118. ->assertLength(array('max' => 32))
  119. ->end()
  120. ;
  121. }
  122. Troubleshooting
  123. ---------------
  124. Make sure your validator method is being called. If in doubt, try throwing an exception:
  125. .. code-block:: php
  126. public function validate(ErrorElement $errorElement, $object)
  127. {
  128. throw new \Exception(__METHOD__);
  129. }
  130. There should not be any validation_groups defined for the form. If you have code like the example below in
  131. your ``Admin`` class, remove the 'validation_groups' entry, the whole $formOptions property or set validation_groups
  132. to an empty array:
  133. .. code-block:: php
  134. protected $formOptions = array(
  135. 'validation_groups' => array()
  136. );