conditional_validation.rst 5.1 KB

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