Statamic Peak

Article

EARLY ACCESS - Compendium Laravel

Découvrez tout ce qu'il y a à savoir sur le framework dans notre compendium Laravel !

Laravel est un framework PHP tout-en-un qui propose de nombreux éléments pour les développeurs d'application web et qui est très orienté. Il se veut accessible aux débutants et developer-friendly avec notamment des outils reconnus comme Eloquent, un ORM avec une base Active Record ou les Collections Laravel, une surcouche aux arrays PHP qui offre une approche objet, fluide et légèrement fonctionnelle.

Laravel propose une base MVC traditionnelle à laquelle s'ajoute de nombreuses fonctionnalités complémentaires que nous détaillerons dans la suite de ce compendium :

  • un controller Laravel est un contrôleur classique. Il est le point d'entrée d'une requête utilisateur. Son rôle est de vérifier les données d'entrées, appeler les services/domaines et diriger l'utilisateur sur la vue souhaitée ou lui renvoyer des données d'API formatées en JSON.
  • un model Laravel est une classe du design pattern Active Directory. Elle inclut donc rarement la logique métier et la validation métier des données. Pour ces éléments, il faut se tourner vers des composants de type Service / Domaine.
  • une view Laravel est une page web qui va être affichée dans le navigateur de l'utilisateur. Elle utilise Blade le langage de templating de Laravel.
  • dans le cas d'une utilisation de Laravel comme API, il est possible d'utiliser les Eloquent Resources, un outil facilitant la transformation d'un model Eloquent en JSON.

Liens utiles

Laravel est disponible de manière open-source et son code source est sur Github.

Sa documentation est versionnée et accessible en ligne sur le site officiel.

Les bases de Laravel

Laravel Routing: Routes et Controller

Les routes permettent de faire le lien entre une URL pointant sur votre application et la fonction qui doit être appelée. Il est possible de définir directement la fonction dans les fichiers de routes de Laravel bien que cela ne soit pas une bonne pratique de répartition du code. Il est préférable de faire des controllers regroupant les fonctions voir même des controllers avec une seule fonction.

Le cycle de vie d'une requête (request lifecycle) est assez simple :

  1. Démarrage du framework notamment la session et l'authentification de la requête
  2. Instantiation de la requête
  3. Autorisation et Validation si c'est une Form request (via les méthodes authorize et rules)
  4. Passage par les middlewares globaux comme par exemple le middleware HandleCors inclus nativement depuis Laravel 7
  5. Recherche de la bonne route
  6. Passage par les middlewares du groupe et de la route

Pour approfondir le sujet, je voue renvoie sur mon précédent article sur le cycle de vie des requête.

Le routing de Laravel se base sur le provider RouteServiceProvider et le dossier routes qui définissent le lien entre les URLs et les fonctions des controllers. Au-delà d'un simple matching, plusieurs fonctionnalités facilitent le développement avec Laravel. Il est possible de définir des arguments dans les urls qui seront transmis aux controllers. Si c'est un id d'une classe Eloquent, il est même possible de récupérer directement le modèle associé automatiquement !

Route::get('/{client?}', ShowDashboard::class)->name('dashboard');

J'ai fait une semaine de conseils focus sur les paramètres de route sur les réseaux sociaux que j'ai synthétisé dans un article appelé Laravel : Route Parameter.

Les fonctions des controllers reçoivent une instance d'une requête (Illuminate\\Http\\Request) qui va nous servir notamment pour valider les données envoyées par l'utilisateur. Pour ce faire, Laravel dispose de nombreuses règles toutes faites qu'il est possible de combiner.

L'exemple suivant valide en 5 lignes que la requête dispose obligatoirement d'un champ dates qui est un tableau de 5 dates distinctes qui sont toutes dans 7 jours 🤯 .

$in7Days = now()->addDays(7);
$request->validateWithBag("myForm", [ 
	"dates"   => "required|array|size:5",
    "dates.*" => "date|distinct|after:".$in7Days->format("Y-m-d"),
]);

En l'absence d'une instance de requête, la validation peut se faire avec la façade Validator.

$validator = Validator::make($request->all(), [
	'title' => 'required|unique:posts|max:255', 
    'body' => 'required', 
]);
if ($validator->fails()) { 
	return redirect('post/create')
    ->withErrors($validator)
    ->withInput();
}

Dans le cas de validations complexes ou qu'on va être amené à réutiliser sur plusieurs requêtes, il est possible de créer une Form Request, une classe qui va contenir la logique propre à la validation et l'authorization de la requête !

J'ai détaillé tout ce qu'il y a à savoir sur le sujet dans mon article sur une request Laravel et comment s'en servir.

Les Form requests c'est bien, mais parfois ça ne suffit pas ! Des fois, vous allez vouloir changer le contenu de votre requête avant qu'elle arrive à votre controller. Par exemple, on pourrait imaginer un middleware qui récupère des coordonnées envoyées par un client et ajoute à la requête l'adresse associée.

Un middleware vous permet également d'intercepter une requête et de rédiger l'utilisateur vers une autre route ou de renvoyer directement une erreur. Un exemple classique c'est la vérification des droits d'accès à une ressource.

Un des middlewares les plus courants concerne la gestion des requêtes Cross Origin. Il existe Laravel CORS, un package spécialisé.

C'est un cas tellement courant que les requêtes CORS sont gérées nativement par Laravel depuis la version 7.

Je vous invite à consulter mon article sur le sujet pour voir plus en détails comment créer un middleware et la liste de ceux disponible par défaut avec Laravel.

Certaines informations de vos clients méritent d'être conservées en mémoire pendant la durée d'une visite sur votre site. Par exemple, si vous avez une page d'accueil avec des onglets et des formulaires, l'envoi et le résultat d'un formulaire doit vous renvoyer sur l'onglet où vous étiez. Si l'utilisateur perd son onglet, il sera perdu et ne pourra potentiellement pas voir votre message de succès ou d'erreur.

Cette information est donc trop longue pour être conservée dans une requête et trop courte pour être stockée en base. C'est ici qu'entre en jeu les sessions ! Comme son nom l'indique, une session est un élément qui va vous servir à stocker et récupérer des informations au cours d'une session d'utilisation de votre service. Quand l'utilisateur quitte son navigateur, les données sont automatiquement supprimées !

Le fonctionnement est très simple, vous pouvez ajouter une information à la session en cours :

$request->session()->put('key', 'value');

Et récupérer l'information de votre choix à partir de sa clef :

$request->session()->get('key');

Pour diminuer la quantité de code à écrire et éviter la dépendance à une instance de request, Laravel a défini un helper spécial :

// Ajouter à la session
session(['key' => 'value']); 
// Récupérer le contenu de la session
session('key');

Dans notre exemple de formulaire, nous avons uniquement besoin de l'information pour la prochaine requête. Comme c'est un cas classique, Laravel propose la méthode flash qui ajoute un élément à la session pour la prochaine requête et le supprime ensuite :

$request->session()->flash('status', 'Task was successful!');

Attention toutefois avec les sessions, ces dernières fonctionnent uniquement dans le contexte d'une requête Http. Il est recommandé de ne pas appeler directement ces méthodes en dehors de vos controllers pour éviter de restreindre l'utilisation de votre code à ce cas précis. Par exemple, un service qui dépendrait d'une session serait inutilisable dans un Job 😕.