X

Règle de validation personnalisée Laravel avec période de date et plusieurs champs


J’ai récemment lu un message sur le forum Laracasts avec une question sur la validation d’une période de date. Décidé d’écrire cet article avec une solution possible.

La situation telle que décrite par l’auteur :

Je veux ajouter une validation aux dates. Je génère un salaire pour les travailleurs mais si le salaire est déjà créé et que l’administrateur essaie de créer le salaire entre des dates déjà créées, je veux lui montrer le message “Veuillez sélectionner des dates différentes” ou autre chose.

Supposons que le salaire entre le 10/01/2022 et le 15/01/2022 soit déjà créé, je ne veux pas créer un autre salaire entre ces dates.

En d’autres termes, comment valider un paire de champs en vérifiant leur certaine règle dans la base de données, quelque chose comme select * from salaries where user_id = ? and date_from < ? and date_to > ?.

Supposons que nous ayons un formulaire ou un point de terminaison d’API qui accepte ces paramètres dans la requête :

  • ID de l’utilisateur
  • date_de
  • date_à
  • montant

Si nous transformons cela dans le langage de Laravel, nous avons ceci :

// app/Http/Controllers/SalaryController.php:

public function store(StoreSalaryRequest $request)

{

Salary::create($request->validated());

 

return redirect()->route('salaries.index');

}

 

// app/Http/Requests/StoreSalaryRequest.php:

class StoreSalaryRequest extends FormRequest

{

public function rules()

{

return [

// ... BIG QUESTION: WHAT DO WE PUT HERE?

];

}

}

Le problème est que nous n’avons pas une telle règle de validation prête à l’emploi dans la liste des règles de validation Laravel par défaut. Nous devons donc créer un coutume règle ici.

Je vais vous donner un exemple avec le nouveau invocable syntaxe des règles de validation personnalisées. Pour une méthode plus ancienne (qui fonctionne toujours), veuillez consulter la documentation Laravel 8 ici.

Tout d’abord, nous créons notre règle :

php artisan make:rule UniqueSalaryRule --invokable

Puis nous remplissons le __invoke méthode avec l’appel de la base de données, pour vérifier si le salaire du user_id et la période existe.

use App\Models\Salary;

use Illuminate\Contracts\Validation\DataAwareRule;

use Illuminate\Contracts\Validation\InvokableRule;

 

class UniqueSalaryRule implements DataAwareRule, InvokableRule

{

protected $data = [];

 

public function __invoke($attribute, $value, $fail)

{

if (Salary::where('user_id', $this->data['user_id'])

->where('date_from', '<=', $value)

->Where('date_to', '>=', $this->data['date_to'])

->exists()) {

$fail('Salary for this period already exists');

}

}

 

public function setData($data)

{

$this->data = $data;

 

return $this;

}

}

Pour accéder aux autres attributs du $requestnous devons mettre en œuvre DataAwareRule interface et ont setData méthode, lisez la section docs appelée Accéder à des données supplémentaires dans la doc officielle.

Enfin, nous activons cette règle de validation dans notre classe FormRequest :

class StoreSalaryRequest extends FormRequest

{

public function rules()

{

return [

'user_id' => 'required',

'date_from' => ['required', new UniqueSalaryRule()],

'date_to' => 'required',

'amount' => 'required',

];

}

}

Et c’est tout : si le date_from et date_to combinaison est invalide, il renverra l’erreur de validation sur le date_from champ.

Encore une fois, ce n’est qu’une façon de procéder : vous pouvez créer une règle de validation personnalisée avec une autre syntaxe, ou même valider les données directement dans le contrôleur au lieu de la demande de formulaire et des règles de validation. Le choix t’appartient!