Laravel 4 : chapitre 17 : Validation

Laravel peut nous simplifier aussi la vie dans le domaine de la validation des entrées et la génération des messages d’erreur afférents.

Le formulaire d’inscription

Nous allons considérer un formulaire d’inscription app/views/inscription.php :

<h2>Inscription au site : </h2>
<form action="http://localhost/laravel/public/inscription" method="post">
  <label for="nom"><strong>Nom :</strong></label>
  <input type="text" name="nom" id="nom"/>
  <label for="pass"><strong>Mot de passe :</strong></label>
  <input type="text" name="passe" id="pass"/>
  <label for="confirmepasse"><strong>Confirmation du mot de passe :</strong></label>
  <input type="text" name="confirmepasse" id="confirmepasse"/>
  <input type="submit" value="S'inscrire"/>
</form>

img65

Les routes

Il nous faut déjà une route pour afficher le formulaire avec l’URL http://localhost/laravel/public/login :

Route::get('login', function()
{
    return View::make('inscription');
});

Il nous faut ensuite une route pour le traitement de retour du formulaire avec l’URL localhost/laravel/public/inscription qui aura cette structure :

Route::post('inscription', function()
{

});

La validation

La validation avec Laravel se fait en définissant des règles :

$rules = array(
    'nom' => 'required|min:5|max:20|alpha',
    'passe' => 'required|min:6|max:10|alpha',
    'confirmepasse' => 'required|same:passe'
);

On définit dans un tableau pour chaque champ les règles correspondantes. Vous pouvez trouver toutes les règles disponibles dans la documentation. Ici par exemple on veut que le nom soit saisi avec un minimum de 5 et un maximum de 20 caractères alphanumériques. Pour le champ confirmepasse on veut qu’il soit identique à passe. Ensuite on crée une instance de la classe Validation en spécifiant les valeurs des champs et les règles :

$validator = Validator::make(Input::all(), $rules);

Il ne reste plus qu’à tester que les règles ont été respectées avec la méthode fails :

if ($validator->fails()) {
    // Traitement en cas d'échec dans au moins une des règles
}

On peut utiliser la méthode inverse passes :

if ($validator->passes()) {
    // Traitement en cas de réussite
}

Les messages

C’est bien de déterminer qu’une règle n’a pas été respectée, encore faut-il savoir laquelle. La classe Validation possède des méthodes pour nous donner des messages relatifs à ces non respects. Voici notre route maintenant :

Route::post('inscription', function()
{
    $rules = array(
        'nom' => 'required|min:5|max:20|alpha',
        'passe' => 'required|min:6|max:10|alpha',
        'confirmepasse' => 'required|same:passe'
    );
    $validator = Validator::make(Input::all(), $rules);

    if ($validator->fails()) {
        echo $validator->messages();
    }
    else echo 'Vous êtes incrit '.Input::get('nom');
});

Et quelques messages en cas de non respect. Par exemple si on ne saisit rien du tout :

{"nom":["The nom field is required."],"passe":["The passe field is required."],"confirmepasse":["The confirmepasse field is required."]}

Avec un nom et un mot de passe trop courts et pas de confirmation du mot de passe :

{"nom":["The nom must be at least 5 characters."],"passe":["The passe must be at least 6 characters."],"confirmepasse":["The confirmepasse field is required."]}

Si la confirmation du mot de passe n’est pas correcte :

{"confirmepasse":["The confirmepasse and passe must match."]}

Bon tout ça semble de bien fonctionner mais c’est en anglais ! Regardez le fichier app/lang/en/validation.php :

<?php

return array(

/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| such as the size rules. Feel free to tweak each of these messages.
|
*/

"accepted"        => "The :attribute must be accepted.",
"active_url"      => "The :attribute is not a valid URL.",
"after"           => "The :attribute must be a date after :date.",
"alpha"           => "The :attribute may only contain letters.",
"alpha_dash"      => "The :attribute may only contain letters, numbers, and dashes.",
"alpha_num"       => "The :attribute may only contain letters and numbers.",
"before"          => "The :attribute must be a date before :date.",
"between"         => array(
"numeric"         => "The :attribute must be between :min - :max.",
"file"            => "The :attribute must be between :min - :max kilobytes.",
"string"          => "The :attribute must be between :min - :max characters.",
),
"confirmed"       => "The :attribute confirmation does not match.",
"different"       => "The :attribute and :other must be different.",
"digits"          => "The :attribute must be :digits digits.",
"digits_between"  => "The :attribute must be between :min and :max digits.",
"email"           => "The :attribute format is invalid.",
"exists"          => "The selected :attribute is invalid.",
"image"           => "The :attribute must be an image.",
"in"              => "The selected :attribute is invalid.",
"integer"         => "The :attribute must be an integer.",
"ip"              => "The :attribute must be a valid IP address.",
"match"           => "The :attribute format is invalid.",
"max"             => array(
"numeric"     => "The :attribute must be less than :max.",
"file"        => "The :attribute must be less than :max kilobytes.",
"string"      => "The :attribute must be less than :max characters.",
),
"mimes"           => "The :attribute must be a file of type: :values.",
"min"             => array(
"numeric"     => "The :attribute must be at least :min.",
"file"        => "The :attribute must be at least :min kilobytes.",
"string"      => "The :attribute must be at least :min characters.",
),
"notin"           => "The selected :attribute is invalid.",
"numeric"         => "The :attribute must be a number.",
"required"        => "The :attribute field is required.",
"required_with"   => "The :attribute field is required when :values is present.",
"same"            => "The :attribute and :other must match.",
"size"            => array(
"numeric"         => "The :attribute must be :size.",
"file"            => "The :attribute must be :size kilobytes.",
"string"          => "The :attribute must be :size characters.",
),
"unique"          => "The :attribute has already been taken.",
"url"             => "The :attribute format is invalid.",

/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/

'custom' => array(),

/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap attribute place-holders
| with something more reader friendly such as E-Mail Address instead
| of "email". This simply helps us make messages a little cleaner.
|
*/

'attributes' => array(),

);

Tous les messages sont ici et rien ne vous empêche de les traduire Tongue Out. Vous pouvez aussi récupérer celui créé par caouecs ici. Mais si vous le faites adoptez une méthode « propre » et créez un dossier fr pour localiser les fichiers de langage et renseignez la ligne correspondante dans le fichier app/config/app.php.

Il est aussi possible de passer le texte des messages comme troisième paramètre de cette façon :

$validator = Validator::make(
    Input::all(),
    $rules,
    array('required' => 'Le champ :attribute est requis.',
));

Utilisation des messages

Maintenant que nous avons des messages nous devons les afficher à l’utilisateur pour qu’il corrige sa saisie. Il faut donc transmettre au formulaire d’inscription ces erreurs et prévoir leur affichage. Pour la transmission c’est simple :

Route::post('inscription', function()
{
    $rules = array(
        'nom' => 'required|min:5|max:20|alpha',
        'passe' => 'required|min:6|max:10|alpha',
        'confirmepasse' => 'required|same:passe'
    );
    $validator = Validator::make(Input::all(), $rules);
    if ($validator->fails()) {
        return Redirect::to('login')->withErrors($validator);
    }
    else echo 'Vous êtes incrit '.Input::get('nom');
});

Et pour le formulaire c’est tout aussi simple :

<form action="http://localhost/laravel/public/inscription" method="post">
    <?php echo $errors->first('nom', '<p>:message</p>'); ?>
    <label for="nom"><strong>Nom :</strong></label>
    <input type="text" name="nom" id="nom"/>
    <?php echo $errors->first('passe', '<p>:message</p>'); ?>
    <label for="pass"><strong>Mot de passe :</strong></label>
    <input type="text" name="passe" id="pass"/>
    <?php echo $errors->first('confirmepasse', '<p>:message</p>'); ?>
    <label for="confirmepasse"><strong>Confirmation du mot de passe :</strong></label>
    <input type="text" name="confirmepasse" id="confirmepasse"/>
    <input type="submit" value="S'inscrire"/>
</form>

Ce qui donne par exemple :

img66

La méthode first récupère la première erreur rencontrée pour un champ donné. On peut aussi obtenir tous les messages pour un champ avec la méthode get :

$messages->get('nom')

Ou alors tester s’il y a des messages pour un champ :

$messages->has('nom')

Renseigner les champs au retour d’erreurs de saisie

Bon il nous reste quand même un petit souci. Il serait bien de renseigner certains champs quand on ré-affiche le formulaire suite à un non respect des règles de saisie. La transmission des valeurs des champs se fait facilement :

Route::post('inscription', function()
{
    $rules = array(
        'nom' => 'required|min:5|max:20|alpha',
        'passe' => 'required|min:6|max:10|alpha',
        'confirmepasse' => 'required|same:passe'
    );
    $validator = Validator::make(Input::all(), $rules);
    if ($validator->fails()) {
        return Redirect::to('login')->withErrors($validator)->withInput();
    }
    else echo 'Vous êtes incrit '.Input::get('nom');
});

Et voici comment les récupérer dans le formulaire avec la méthode old :

<form action="http://localhost/laravel/public/inscription" method="post">
    <?php echo $errors->first('nom', '<p>:message</p>'); ?>
    <label for="nom"><strong>Nom :</strong></label>
    <input type="text" name="nom" id="nom" value="<?php echo Input::old('nom'); ?>" />
    <?php echo $errors->first('passe', '<p>:message</p>'); ?>
    <label for="pass"><strong>Mot de passe :</strong></label>
    <input type="password" name="passe" id="pass" value="<?php echo Input::old('passe'); ?>" />
    <?php echo $errors->first('confirmepasse', '<p>:message</p>'); ?>
    <label for="confirmepasse"><strong>Confirmation du mot de passe :</strong></label>
    <input type="password" name="confirmepasse" id="confirmepasse"/>
    <input type="submit" value="S'inscrire"/>
</form>

Si vous utilisez la classe Form le remplissage des champs avec les anciennes valeurs est automatique. Voici l’équivalent du formulaire ci-dessus mais cette fois en utilisant la classe Form et Blade :

{{ $errors->first('nom', '<p>:message</p>') }}
{{ Form::open(array('url' => 'inscription')) }}
<strong>{{ Form::label('nom', 'Nom : ') }}</strong>
{{ Form::text('nom'); }}<br>
{{ $errors->first('passe', '<p>:message</p>') }}
<strong>{{ Form::label('pass', 'Mot de passe : ') }}</strong>
{{ Form::password('pass'); }}<br>
{{ $errors->first('confirmepasse', '<p>:message</p>') }}
<strong>{{ Form::label('confirmepasse', 'Confirmation du mot de passe :') }}</strong>
{{ Form::password('confirmepasse') }}<br>
{{ Form::submit('S\'inscrire') }}
{{ Form::close() }}

Vous n’êtes bien sûr pas obligés d’utiliser ces possibilités mais ce serait dommage Tongue Out.

2 réflexions sur “Laravel 4 : chapitre 17 : Validation

  1. Thaddius_Brokk dit :

    Bonjour,
    j’aimerai savoir si quelqu’un bloquerait aussi à l’affichage des messages. Voici mes routes :

    Route::get(‘login’, function()
    {
    return View::make(‘inscription’);
    });

    Route::post(‘inscription’, function (){
    $rules = array(
    ‘nom’ => ‘required|min:5|max:20|alpha’,
    ’email’ => ‘required|email’,
    ‘passe’ => ‘required|min:6|max:10|alpha’,
    ‘confirmepasse’ => ‘required|same:passe’
    );
    $validator = Validator::make(Input::all(), $rules);
    if ($validator->fails()) {
    echo $validator->messages();
    }
    else echo ‘Vous êtes inscrit’.Input::get(‘nom’);

    });

    j’arrive pas à cerner pourquoi ma page Login est vide même en ajoutant la redirection ‘withErrors’

    Merci tout le monde

    • Thaddius_Brokk dit :

      Route::get(‘/’,[‘as’ => ‘form’, function()
      {
      return View::make(‘inscription’);
      }]);

      Route::post(‘/’, [‘after’ => ‘form’, function (){
      $rules = array(
      ‘nom’ => ‘required|min:5|max:20|alpha’,
      ’email’ => ‘required|email’,
      ‘passe’ => ‘required|min:6|max:10|alpha’,
      ‘confirmepasse’ => ‘required|same:passe’
      );
      $validator = Validator::make(Input::all(), $rules);
      if ($validator->fails()) {
      echo $validator->messages();
      }
      else echo ‘Vous êtes inscrit’.Input::get(‘nom’);

      }]);

      C’est bon 🙂
      J’ai réussi en faisant ça

Laisser un commentaire