English spoken conference

Symfony 5: The Fast Track

A new book to learn about developing modern Symfony 5 applications.

Support this project

WARNING: You are browsing the documentation for Symfony 2.0 which is not maintained anymore. Consider upgrading your projects to Symfony 4.3.

Callback

Callback

The purpose of the Callback assertion is to let you create completely custom validation rules and to assign any validation errors to specific fields on your object. If you're using validation with forms, this means that you can make these custom errors display next to a specific field, instead of simply at the top of your form.

This process works by specifying one or more callback methods, each of which will be called during the validation process. Each of those methods can do anything, including creating and assigning validation errors.

Note

A callback method itself doesn't fail or return any value. Instead, as you'll see in the example, a callback method has the ability to directly add validator "violations".

Applies to class
Options
Class Callback
Validator CallbackValidator

Setup

  • YAML
    1
    2
    3
    4
    5
    # src/Acme/BlogBundle/Resources/config/validation.yml
    Acme\BlogBundle\Entity\Author:
        constraints:
            - Callback:
                methods:   [isAuthorValid]
    
  • Annotations
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    // src/Acme/BlogBundle/Entity/Author.php
    namespace Acme\BlogBundle\Entity;
    
    use Symfony\Component\Validator\Constraints as Assert;
    
    /**
     * @Assert\Callback(methods={"isAuthorValid"})
     */
    class Author
    {
    }
    
  • XML
    1
    2
    3
    4
    5
    6
    7
    8
    <!-- src/Acme/BlogBundle/Resources/config/validation.xml -->
    <class name="Acme\BlogBundle\Entity\Author">
        <constraint name="Callback">
            <option name="methods">
                <value>isAuthorValid</value>
            </option>
        </constraint>
    </class>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    // src/Acme/BlogBundle/Entity/Author.php
    namespace Acme\BlogBundle\Entity;
    
    use Symfony\Component\Validator\Mapping\ClassMetadata;
    use Symfony\Component\Validator\Constraints as Assert;
    
    class Author
    {
        public static function loadValidatorMetadata(ClassMetadata $metadata)
        {
            $metadata->addConstraint(new Assert\Callback(array(
                'methods' => array('isAuthorValid'),
            )));
        }
    }
    

The Callback Method

The callback method is passed a special ExecutionContext object. You can set "violations" directly on this object and determine to which field those errors should be attributed:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
// ...
use Symfony\Component\Validator\ExecutionContext;

class Author
{
    // ...
    private $firstName;

    public function isAuthorValid(ExecutionContext $context)
    {
        // somehow you have an array of "fake names"
        $fakeNames = array();

        // check if the name is actually a fake name
        if (in_array($this->getFirstName(), $fakeNames)) {
            $propertyPath = $context->getPropertyPath() . '.firstName';
            $context->setPropertyPath($propertyPath);
            $context->addViolation('This name sounds totally fake!', array(), null);
        }
    }
}

Options

methods

type: array default: array() [default option]

This is an array of the methods that should be executed during the validation process. Each method can be one of the following formats:

  1. String method name

    If the name of a method is a simple string (e.g. isAuthorValid), that method will be called on the same object that's being validated and the ExecutionContext will be the only argument (see the above example).

  2. Static array callback

    Each method can also be specified as a standard array callback:

    • YAML
      1
      2
      3
      4
      5
      6
      # src/Acme/BlogBundle/Resources/config/validation.yml
      Acme\BlogBundle\Entity\Author:
          constraints:
              - Callback:
                  methods:
                      -    [Acme\BlogBundle\MyStaticValidatorClass, isAuthorValid]
      
    • Annotations
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      // src/Acme/BlogBundle/Entity/Author.php
      use Symfony\Component\Validator\Constraints as Assert;
      
      /**
       * @Assert\Callback(methods={
       *     { "Acme\BlogBundle\MyStaticValidatorClass", "isAuthorValid"}
       * })
       */
      class Author
      {
      }
      
    • XML
      1
      2
      3
      4
      5
      6
      7
      8
      9
      <!-- src/Acme/BlogBundle/Resources/config/validation.xml -->
      <class name="Acme\BlogBundle\Entity\Author">
          <constraint name="Callback">
              <option name="methods">
                  <value>Acme\BlogBundle\MyStaticValidatorClass</value>
                  <value>isAuthorValid</value>
              </option>
          </constraint>
      </class>
      
    • PHP
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      // src/Acme/BlogBundle/Entity/Author.php
      
      use Symfony\Component\Validator\Mapping\ClassMetadata;
      use Symfony\Component\Validator\Constraints\Callback;
      
      class Author
      {
          public $name;
      
          public static function loadValidatorMetadata(ClassMetadata $metadata)
          {
              $metadata->addConstraint(new Callback(array(
                  'methods' => array('isAuthorValid'),
              )));
          }
      }
      

    In this case, the static method isAuthorValid will be called on the Acme\BlogBundle\MyStaticValidatorClass class. It's passed both the original object being validated (e.g. Author) as well as the ExecutionContext:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    namespace Acme\BlogBundle;
    
    use Symfony\Component\Validator\ExecutionContext;
    use Acme\BlogBundle\Entity\Author;
    
    class MyStaticValidatorClass
    {
        public static function isAuthorValid(Author $author, ExecutionContext $context)
        {
            // ...
        }
    }
    

    Tip

    If you specify your Callback constraint via PHP, then you also have the option to make your callback either a PHP closure or a non-static callback. It is not currently possible, however, to specify a service as a constraint. To validate using a service, you should create a custom validation constraint and add that new constraint to your class.

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.