conditional_validation.rst 5.5 KB

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