Les requêtes et les réponses avec Symfony 6

Le composant HttpKernel fournit un processus structuré pour convertir une requête en réponse en utilisant le composant EventDispatcher. Il est suffisamment flexible pour créer un framework complet (Symfony), un micro-framework (Silex) ou un système CMS avancé (Drupal).

composer require symfony/http-kernel

Note : Si vous installez ce composant en dehors d’une application Symfony, vous devez exiger le fichier vendor/autoload.php dans votre code pour activer le mécanisme de chargement automatique des classes fourni par Composer. Lisez cet article pour plus de détails.

Chaque interaction web HTTP commence par une requête et se termine par une réponse. Votre travail en tant que développeur est de créer du code PHP qui lit les informations de la requête (par exemple, l’URL) et crée et renvoie une réponse (par exemple, une page HTML ou une chaîne JSON). Voici un aperçu simplifié du flux de travail des demandes dans les applications Symfony :

  • L’utilisateur demande une ressource dans un navigateur ;
  • Le navigateur envoie une requête au serveur ;
  • Symfony donne à l’application un objet Request ;
  • L’application génère un objet Response en utilisant les données de l’objet Request ;
  • Le serveur renvoie la réponse au navigateur ;
  • Le navigateur affiche la ressource à l’utilisateur.

Généralement, une sorte de cadre ou de système est construit pour gérer toutes les tâches répétitives (par exemple, le routage, la sécurité, etc) afin qu’un développeur puisse construire chaque page de l’application. La manière exacte dont ces systèmes sont construits varie considérablement. Le composant HttpKernel fournit une interface qui formalise le processus consistant à partir d’une demande et à créer la réponse appropriée. Ce composant est destiné à être le cœur de toute application ou cadre de travail, quelle que soit la diversité de l’architecture de ce système :

namespace Symfony\Component\HttpKernel;

use Symfony\Component\HttpFoundation\Request;

interface HttpKernelInterface
{
    // ...

    /**
     * @return Response A Response instance
     */
    public function handle(
        Request $request,
        int $type = self::MAIN_REQUEST,
        bool $catch = true
    );
}

En interne, HttpKernel::handle() – l’implémentation concrète de HttpKernelInterface::handle() – définit un flux de travail qui commence par une demande et se termine par une réponse.

Les détails exacts de ce flux de travail sont la clé pour comprendre comment le noyau (et le Symfony Framework ou toute autre bibliothèque qui utilise le noyau) fonctionne.

1) L’événement kernel.request

Buts typiques : Ajouter des informations supplémentaires à la requête, initialiser des parties du système ou renvoyer une réponse si possible (par exemple, une couche de sécurité qui refuse l’accès).

Tableau d’information des événements du noyau

Le premier événement distribué dans HttpKernel::handle est kernel.request, qui peut avoir une variété de récepteurs différents.

Les auditeurs de cet événement peuvent être très variés. Certains auditeurs – comme un auditeur de sécurité – peuvent avoir suffisamment d’informations pour créer immédiatement un objet Response. Par exemple, si un auditeur de sécurité détermine qu’un utilisateur n’a pas d’accès, il peut renvoyer une RedirectResponse vers la page de connexion ou une réponse 403 Access Denied.

Si une réponse est renvoyée à ce stade, le processus passe directement à l’événement kernel.response.

D’autres écouteurs initialisent des choses ou ajoutent des informations supplémentaires à la demande. Par exemple, un écouteur peut déterminer et définir la locale sur l’objet Request.

Un autre écouteur commun est le routage. Un auditeur de routage peut traiter la demande et déterminer le contrôleur qui doit être rendu (voir la section suivante). En fait, l’objet Request possède un sac « attributes » qui est l’endroit idéal pour stocker ces données supplémentaires, spécifiques à l’application, concernant la requête. Cela signifie que si votre écouteur de routeur détermine d’une manière ou d’une autre le contrôleur, il peut le stocker dans les attributs de la requête (qui peuvent être utilisés par votre résolveur de contrôleur).

Dans l’ensemble, le but de l’événement kernel.request est soit de créer et de renvoyer directement une réponse, soit d’ajouter des informations à la demande (par exemple, en définissant la locale ou d’autres informations sur les attributs de la demande).

Note : Lors de la définition d’une réponse pour l’événement kernel.request, la propagation est arrêtée. Cela signifie que les listeners avec une priorité inférieure ne seront pas exécutés.

2) Résoudre le contrôleur

En supposant qu’aucun écouteur kernel.request n’ait pu créer une réponse, l’étape suivante de HttpKernel consiste à déterminer et à préparer (c’est-à-dire résoudre) le contrôleur. Le contrôleur est la partie du code de l’application finale qui est responsable de la création et du retour de la réponse pour une page spécifique. La seule exigence est qu’il s’agisse d’un appelable PHP – c’est-à-dire une fonction, une méthode sur un objet ou un Closure.

Mais la façon dont vous déterminez le contrôleur exact d’une requête dépend entièrement de votre application. C’est le travail du « controller resolver » – une classe qui implémente la ControllerResolverInterface et qui est l’un des arguments du constructeur de HttpKernel.

Votre travail consiste à créer une classe qui implémente l’interface et à remplir sa méthode : getController(). En fait, il existe déjà une implémentation par défaut, que vous pouvez utiliser directement ou apprendre : ControllerResolver. Cette implémentation est expliquée plus en détail dans l’encadré ci-dessous :

namespace Symfony\Component\HttpKernel\Controller;

use Symfony\Component\HttpFoundation\Request;

interface ControllerResolverInterface
{
    public function getController(Request $request);
}

En interne, la méthode HttpKernel::handle() appelle d’abord getController() sur le résolveur de contrôleur. Cette méthode reçoit la requête et est responsable de la détermination et du retour d’un appelant PHP (le contrôleur) basé sur les informations de la requête.

3) L’événement kernel.controller

Buts typiques : Initialiser les choses ou modifier le contrôleur juste avant l’exécution du contrôleur.

Tableau d’information des événements du noyau

Une fois que l’appelant du contrôleur a été déterminé, HttpKernel::handle() envoie l’événement kernel.controller. Les auditeurs de cet événement peuvent initialiser une partie du système qui doit être initialisée après que certaines choses aient été déterminées (par exemple, le contrôleur, les informations de routage) mais avant que le contrôleur ne soit exécuté. Pour quelques exemples, voir la section Symfony ci-dessous.

Les auditeurs de cet événement peuvent aussi changer complètement le contrôleur appelable en appelant ControllerEvent::setController sur l’objet événement qui est passé aux auditeurs de cet événement.

composer require symfony/orm-pack
composer require --dev symfony/maker-bundle