Définir les règles de validation

Difficulté Facile
Note
Thématiques
PHP, Web
Mis à jour le vendredi 3 mai 2013

Les différentes formes de règles

Pour définir ces règles de validation, ou contraintes, il existe deux moyens :

  1. Le premier est d'utiliser les annotations, vous les connaissez maintenant. Leur avantage est d'être situées au sein même de l'entité, et juste à côté des annotations du mapping Doctrine2 si vous les utilisez également pour votre mapping.

  2. Le deuxième est d'utiliser le YAML, XML ou PHP. Vous placez donc vos règles de validation hors de l'entité, dans un fichier séparé.

Les deux moyens sont parfaitement équivalents en termes de fonctionnalités. Le choix se fait donc selon vos préférences. Dans la suite du cours, j'utiliserai les annotations, car je trouve extrêmement pratique de centraliser règles de validation et mapping Doctrine au même endroit. Facile à lire et à modifier. ;)

Définir les règles de validation

Préparation

Nous allons prendre l'exemple de notre entité Article pour construire nos règles. La première étape consiste à déterminer les règles que nous voulons avec des mots, comme ceci :

  • La date doit être une date valide ;

  • Le titre doit faire au moins 10 caractères de long ;

  • Le contenu ne doit pas être vide ;

  • L'auteur doit faire au moins 2 caractères de long ;

  • L'image liée doit être valide selon les règles attachées à l'objet Image.

À partir de cela, nous pourrons convertir ces mots en annotations.

Annotations

Pour définir les règles de validation, nous allons donc utiliser les annotations. La première chose à savoir est le namespace des annotations à utiliser. Souvenez-vous, pour le mapping Doctrine c'était @ORM, ici nous allons utiliser @Assert, donc le namespace complet est le suivant :

<?php
use Symfony\Component\Validator\Constraints as Assert;

Ce use est à rajouter au début de l'objet que l'on va valider, notre entité Article en l'occurrence. En réalité, vous pouvez définir l'alias à autre chose qu'Assert. Mais c'est une convention qui s'est installée, donc autant la suivre pour avoir un code plus facilement lisible pour les autres développeurs.

Ensuite, il ne reste plus qu'à ajouter les annotations pour traduire les règles que l'on vient de lister. Sans plus attendre, voici donc la syntaxe à respecter. Exemple avec notre objet Article :

<?php

namespace Sdz\BlogBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
// N'oubliez pas de rajouter ce « use », il définit le namespace pour les annotations de validation
use Symfony\Component\Validator\Constraints as Assert;

use Doctrine\Common\Collections\ArrayCollection;

/**
 * Sdz\BlogBundle\Entity\Article
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="Sdz\BlogBundle\Entity\ArticleRepository")
 */
class Article
{
  /**
   * @var integer $id
   *
   * @ORM\Column(name="id", type="integer")
   * @ORM\Id
   * @ORM\GeneratedValue(strategy="AUTO")
   */
  private $id;

  /**
   * @var date $date
   *
   * @ORM\Column(name="date", type="date")
   * @Assert\DateTime()
   */
  private $date;

  /**
   * @var string $titre
   *
   * @ORM\Column(name="titre", type="string", length=255)
   * @Assert\MinLength(10)
   */
  private $titre;
    
  /**
   * @var text $contenu
   *
   * @ORM\Column(name="contenu", type="text")
   * @Assert\NotBlank()
   */
  private $contenu;
    
  /**
   * @var string $auteur
   *
   * @ORM\Column(name="auteur", type="string", length=255)
   * @Assert\MinLength(2)
   */
  private $auteur;
    
  /**
   * @ORM\OneToOne(targetEntity="Sdz\BlogBundle\Entity\Image", cascade={"persist"})
   * @Assert\Valid()
   */
  private $image;
  
  // …
}

Vraiment pratique d'avoir les métadonnées Doctrine et les règles de validation au même endroit, n'est-ce pas ?

Syntaxe

Revenons un peu sur les annotations que l'on a ajoutées. Nous avons utilisé la forme simple, qui est construite comme ceci :

@Assert\Contrainte(valeur de l'option par défaut)

Avec :

  • La Contrainte, qui peut être, comme vous l'avez vu, NotBlank ou MinLength, etc. Nous voyons plus loin toutes les contraintes possibles.

  • La Valeur entre parenthèses, qui est la valeur de l'option par défaut. En effet chaque contrainte a plusieurs options, dont une par défaut souvent intuitive. Par exemple, l'option par défaut de MinLength (« longueur minimale » en français) est évidemment la valeur de la longueur minimale que l'on veut appliquer, 10 pour le titre.

Mais on peut aussi utiliser la forme étendue qui permet de personnaliser la valeur de plusieurs options en même temps, comme ceci :

@Assert\Contrainte(option1="valeur1", option2="valeur2", …)

Les différentes options diffèrent d'une contrainte à une autre, mais voici un exemple avec la contrainte MinLength :

@Assert\MinLength(limit=10, message="Le titre doit faire au moins {{ limit }} caractères.")

Bien entendu, vous pouvez mettre plusieurs contraintes sur un même attribut. Par exemple pour un attribut numérique telle une note, on pourrait mettre les deux contraintes suivantes :

<?php
/**
 * @Assert\Min(0)
 * @Assert\Max(20)
 */
private $note

Vous savez tout ! Il n'y a rien de plus à connaître sur les annotations. À part les contraintes existantes et leurs options, évidemment.

Liste des contraintes existantes

Voici un tableau qui regroupe la plupart des contraintes, à avoir sous la main lorsque vous définissez vos règles de validation ! Elles sont bien entendu toutes documentées, donc n'hésitez pas à vous référer à la documentation officielle pour toute information supplémentaire.

Toutes les contraintes disposent de l'option message, qui est le message à afficher lorsque la contrainte est violée. Je n'ai pas répété cette option dans les tableaux suivants, mais sachez qu'elle existe bien à chaque fois.

Contraintes de base :

Contrainte

Rôle

Options

NotBlank
Blank

La contrainte NotBlank vérifie que la valeur soumise n'est ni une chaîne de caractères vide, ni NULL.
La contrainte Blank fait l'inverse.

-

True
False

La contrainte True vérifie que la valeur vaut true, 1 ou "1".
La contrainte False vérifie que la valeur vaut false, 0 ou "0".

-

Type

La contrainte Type vérifie que la valeur est bien du type donné en argument.

type (option par défaut) : le type duquel doit être la valeur, parmi array, bool, int, object, etc.

Contraintes sur des chaînes de caractères :

Contrainte

Rôle

Options

Email

La contrainte Email vérifie que la valeur est une adresse e-mail valide.

checkMX (défaut : false) : si défini à true, Symfony2 va vérifier les MX de l'e-mail via la fonction checkdnsrr.

MinLength
MaxLength

La contrainte MinLength vérifie que la valeur donnée fait au moins X caractères de long.
MaxLength, au plus X caractères de long.

limit (option par défaut) : le seuil de longueur, en nombre de caractères.
charset (défaut : UTF-8) : le charset à utiliser pour calculer la longueur.

Url

La contrainte Url vérifie que la valeur est une adresse URL valide.

protocols (défaut : array('http', 'https')) : définit les protocoles considérés comme valides.
Si vous voulez accepter les URL en ftp://, ajoutez-le à cette option.

Regex

La contrainte Regex vérifie la valeur par rapport à une regex.

pattern (option par défaut) : la regex à faire correspondre.
match (défaut : true) : définit si la valeur doit (true) ou ne doit pas (false) correspondre à la regex.

Ip

La contrainte Ip vérifie que la valeur est une adresse IP valide.

type (défaut : 4) : version de l'IP à considérer. 4 pour IPv4, 6 pour IPv6, all pour toutes les versions, et d'autres.

Language

La contrainte Language vérifie que la valeur est un code de langage valide selon la norme.

-

Locale

La contrainte Locale vérifie que la valeur est une locale valide. Exemple : fr ou fr_FR.

-

Country

La contrainte Country vérifie que la valeur est un code pays en 2 lettres valide. Exemple : fr.

-

Contraintes sur les nombres :

Contrainte

Rôle

Options

Max
Min

La contrainte Max vérifie que la valeur ne dépasse pas X.
Min, que la valeur dépasse ce X.

limit (option par défaut) : la valeur seuil.
invalidMessage : message d'erreur lorsque la valeur n'est pas un nombre.

Contraintes sur les dates :

Contrainte

Rôle

Options

Date

La contrainte Date vérifie que la valeur est un objet de type Datetime, ou une chaîne de caractères du type YYYY-MM-DD.

-

Time

La contrainte Time vérifie que la valeur est un objet de type Datetime, ou une chaîne de caractères du type HH:MM:SS.

-

DateTime

La contrainte Datetime vérifie que la valeur est un objet de type Datetime, ou une chaîne de caractères du type YYYY-MM-DD HH:MM:SS.

-

Contraintes sur les fichiers :

Contrainte

Rôle

Options

File

La contrainte File vérifie que la valeur est un fichier valide, c'est-à-dire soit une chaîne de caractères qui point vers un fichier existant, soit une instance de la classe File (ce qui inclut UploadedFile).

maxSize : la taille maximale du fichier. Exemple : 1M ou 1k.
mimeTypes : mimeType(s) que le fichier doit avoir.

Image

La contrainte Image vérifie que la valeur est valide selon la contrainte précédente File (dont elle hérite les options), sauf que les mimeTypes acceptés sont automatiquement définis comme ceux de fichiers images. Il est également possible de mettre des contraintes sur la hauteur max ou la largeur max de l'image.

maxSize : la taille maximale du fichier. Exemple : 1M ou 1k.
minWidth / maxWidth : la largeur minimale et maximale que doit respecter l'image.
minHeight / maxHeight : la hauteur minimale et maximale que doit respecter l'image.

L'auteur