Ver índice de contenidos del libro

A.15. ValidatorServiceProvider

El proveedor ValidatorServiceProvider permite validar información, lo que es especialmente útil cuando se utiliza junto al proveedor de formularios FormServiceProvider (aunque también se puede utilizar de manera independiente).

A.15.1. Parámetros de configuración

El proveedor define los siguientes parámetros configurables:

  • validator.validator_service_ids: un array con los nombres de los servicios registrados como validadores.

A.15.2. Servicios proporcionados

El proveedor proporciona los siguientes servicios:

  • validator: es una instancia de la clase Validator.
  • validator.mapping.class_metadata_factory: es una factoría de clases que se encargan de procesar los metadatos con los que se define la información de validación. Si defines un método estático llamado loadValidatorMetadata() en tu clase de datos, recibirá como argumento un objeto de tipo ClassMetadata. Después ya puedes definir tus reglas de validación en esta instancia de ClassMetadata.

A.15.3. Cómo se registra el proveedor

El siguiente código muestra un ejemplo de cómo registrar este proveedor:

$app->register(new Silex\Provider\ValidatorServiceProvider());

Nota El componente Validator de Symfony se incluye cuando descargas Silex en forma de archivo comprimido. Si instalas Silex mediante Composer, debes añadir esta dependencia ejecutando el siguiente comando:

$ composer require symfony/validator

A.15.4. Ejemplos de uso

El servicio más utilizado del proveedor es validator, que es con el que se realizan la mayor parte de las operaciones, tal y como muestran los ejemplos de las siguientes secciones.

A.15.4.1. Validando información

Para validar cualquier dato o información, utiliza directamente el método validateValue():

use Symfony\Component\Validator\Constraints as Assert;
 
$app->get('/validar/{email}', function ($email) use ($app) {
    $errors = $app['validator']->validateValue($email, new Assert\Email());
 
    if (count($errors) > 0) {
        return (string) $errors;
    } else {
        return 'El email es válido';
    }
});

A.15.4.2. Validando arrays asociativos

La validación de los arrays asociativos es similar a la de los valores simples, pero utiliza una colección de constraints o condiciones de validación:

use Symfony\Component\Validator\Constraints as Assert;
 
class Book
{
    public $title;
    public $author;
}
 
class Author
{
    public $first_name;
    public $last_name;
}
 
$book = array(
    'title' => 'My Book',
    'author' => array(
        'first_name' => 'Fabien',
        'last_name'  => 'Potencier',
    ),
);
 
$constraint = new Assert\Collection(array(
    'title' => new Assert\Length(array('min' => 10)),
    'author' => new Assert\Collection(array(
        'first_name' => array(new Assert\NotBlank(), new Assert\Length(array('min' => 10))),
        'last_name'  => new Assert\Length(array('min' => 10)),
    )),
));
$errors = $app['validator']->validateValue($book, $constraint);
 
if (count($errors) > 0) {
    foreach ($errors as $error) {
        echo $error->getPropertyPath().' '.$error->getMessage()."\n";
    }
} else {
    echo 'El libro es válido';
}

A.15.4.3. Validando objetos

Para validar los datos de una clase, define las condiciones de validación para sus propiedades y sus métodos de tipo getter y después utiliza el método validate():

use Symfony\Component\Validator\Constraints as Assert;
 
$author = new Author();
$author->first_name = 'Fabien';
$author->last_name = 'Potencier';
 
$book = new Book();
$book->title = 'My Book';
$book->author = $author;
 
$metadata = $app['validator.mapping.class_metadata_factory']->getMetadataFor('Author');
$metadata->addPropertyConstraint('first_name', new Assert\NotBlank());
$metadata->addPropertyConstraint('first_name', new Assert\Length(array('min' => 10)));
$metadata->addPropertyConstraint('last_name', new Assert\Length(array('min' => 10)));
 
$metadata = $app['validator.mapping.class_metadata_factory']->getMetadataFor('Book');
$metadata->addPropertyConstraint('title', new Assert\Length(array('min' => 10)));
$metadata->addPropertyConstraint('author', new Assert\Valid());
 
$errors = $app['validator']->validate($book);
 
if (count($errors) > 0) {
    foreach ($errors as $error) {
        echo $error->getPropertyPath().' '.$error->getMessage()."\n";
    }
} else {
    echo 'El autor es válido';
}

La validación también se puede configurar añadiendo a tu clase un método llamado loadValidatorMetadata():

use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints as Assert;
 
class Book
{
    public $title;
    public $author;
 
    static public function loadValidatorMetadata(ClassMetadata $metadata)
    {
        $metadata->addPropertyConstraint('title', new Assert\Length(array('min' => 10)));
        $metadata->addPropertyConstraint('author', new Assert\Valid());
    }
}
 
class Author
{
    public $first_name;
    public $last_name;
 
    static public function loadValidatorMetadata(ClassMetadata $metadata)
    {
        $metadata->addPropertyConstraint('first_name', new Assert\NotBlank());
        $metadata->addPropertyConstraint('first_name', new Assert\Length(array('min' => 10)));
        $metadata->addPropertyConstraint('last_name', new Assert\Length(array('min' => 10)));
    }
}
 
$app->get('/validate/{email}', function ($email) use ($app) {
    $author = new Author();
    $author->first_name = 'Fabien';
    $author->last_name = 'Potencier';
 
    $book = new Book();
    $book->title = 'My Book';
    $book->author = $author;
 
    $errors = $app['validator']->validate($book);
 
    if (count($errors) > 0) {
        foreach ($errors as $error) {
            echo $error->getPropertyPath().' '.$error->getMessage()."\n";
        }
    } else {
        echo 'El autor es válido';
    }
});

Nota Utiliza el método addGetterConstraint() para definir las condiciones de validación de los getters y el método addConstraint() para definir esas condiciones sobre la propia clase.

A.15.4.4. Traduciendo los mensajes de error

Si quieres traducir los mensajes de error mostrados por defecto, utiliza el proveedor de traducción y registra los nuevos mensajes bajo el dominio llamado validators:

$app['translator.domains'] = array(
    'validators' => array(
        'es' => array(
            'This value should be a valid number.' => 'Este valor debe ser un número.',
        ),
    ),
);