21 octobre 2021 170.092K

Formation Laravel : Request

Nous avons vu dans le chapitre Eloquent (partie 2 du cours) ce qu’était le CRUD et un controller resource. Nous allons donc reprendre ces principes d’actions et nous pencher plus particulièrement sur la méthode store() qui permet d’enregistrer un nouvel élément dans la base de donnée grâce à la méthode POST (que j’espère vous connaissez déjà ^^).

Pour cet exemple imaginons que nous avons avons un formulaire qui enregistre des livres avec leur nom, l’auteur, le prix et une courte description. Sans oublier bien sûr le token CSRF.

<form action="{{ route('books.store') }}" method="POST">
    @csrf
    <label for="title">Nom du livre : </label>
    <input type="text" name="title" value="Le Monde comme volonté et comme représentation">
    
    <label for="author">Auteur du livre : </label>
    <input type="text" name="author" value="Arthur Schopenhauer">
    
    <label for="price">Prix du produit : </label>
    <input type="number" name="price" step="0.01" value="19.99">
    
    <label for="description">Description du produit : </label>
    <textarea name="description">Œuvre majeure d'Arthur Schopenhauer regroupant 4 livres chacun traitant un thème essentiel : épistémologie, métaphysique, esthétique et éthique.
    </textarea>
    
    <button type="submit" value="Envoyer">
</form>

On définit la route qui nous permettra d’accéder à ce formulaire ainsi que la route utiliser dans l’attribut action du notre formulaire pour recevoir les données :

Route::get('/livres/create', 'BookController@create')->name('books.create');
Route::post('/livres', 'BookController@store')->name('books.store');

Ensuite on lance dans le terminal la commande que l’on a vu au chapitre sur les Controllers qui nous permet de créer un controller resource :

php artisan make:controller --resource

Nous nous rendons enfin dans notre controller BookController :

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class BookController {
    public function create() {
        return view('create_book');
    }

    public function store(Request $request) {
        // la méthode qui récupèrera les données du formulaire
    }
}

Bien entendu ce controller contiendra toutes les méthodes d’un controller resource (c’est à dire : index, create, store, edit, update, delete). Mais pour l’exemple je resterai focus sur ce qui nous intéresse.

1. La Class Request

Lorsque vous créez un nouveau controller vous pouvez remarquer que le namespace d’une class est directement ajouté, celui de la class Request : use Illuminate\Http\Request.

Cette Class extend une autre class Request qui provient du package de Symfony. En vous rendant dans la fonction __construct() voici ce que l’on y trouve :

/**
 * @param array                $query      The GET parameters
 * @param array                $request    The POST parameters
 * @param array                $attributes The request attributes (parameters parsed from the PATH_INFO, ...)
 * @param array                $cookies    The COOKIE parameters
 * @param array                $files      The FILES parameters
 * @param array                $server     The SERVER parameters
 * @param string|resource|null $content    The raw body data
 */
public function __construct(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null)
{
    $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content);
}

On y voit plusieurs tableaux passés en paramètre :

$query : récupère les valeurs d’une requête en get (équivalent de $_GET)
$request : récupère les valeurs d’une requête en post (équivalent de $_POST)
$attributes : c’est le seul tableau qui n’est pas peuplé par la requête elle-même mais plutôt par l’application. Cela nous permet d’y ajouter des attributs supplémentaires.
$cookies : l’ensemble des données stockées dans les cookies (notamment la valeur ‘XSRF-TOKEN’ que l’on a vu dans le chapitre précédent).
$files : récupère les données des fichiers uploadés (équivalent de $_FILES)
$server : qui sont les informations serveur de la requête. Avec notamment ‘REQUEST_METHOD’ qui détermine la méthode de la requête, ‘QUERY_STRING’ s’il s’agit d’une requête en GET, ‘REQUEST_URI’ qui est l’url de la requête etc…

Vous pouvez tester de dd() ces données si vous êtes curieux 🙂

Les propriétés $query$request$attributes et $cookies sont des instances de ParameterBag comme on peut le voir dans la méthode initialize() :

/**
 * Sets the parameters for this request.
 *
 * This method also re-initializes all properties.
 *
 * @param array                $query      The GET parameters
 * @param array                $request    The POST parameters
 * @param array                $attributes The request attributes (parameters parsed from the PATH_INFO, ...)
 * @param array                $cookies    The COOKIE parameters
 * @param array                $files      The FILES parameters
 * @param array                $server     The SERVER parameters
 * @param string|resource|null $content    The raw body data
 */
public function initialize(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null)
{
    $this->request = new ParameterBag($request);
    $this->query = new ParameterBag($query);
    $this->attributes = new ParameterBag($attributes);
    $this->cookies = new ParameterBag($cookies);
    $this->files = new FileBag($files);
    $this->server = new ServerBag($server);
    $this->headers = new HeaderBag($this->server->getHeaders());

    $this->content = $content;
    $this->languages = null;
    $this->charsets = null;
    $this->encodings = null;
    $this->acceptableContentTypes = null;
    $this->pathInfo = null;
    $this->requestUri = null;
    $this->baseUrl = null;
    $this->basePath = null;
    $this->method = null;
    $this->format = null;
}

Et l’on peut appliquer à ces instances une multitude de méthodes permettant de récupérer, filtrer, modifier leurs données.

Ok ! Donc dans notre controller on a accès seulement à cette propriété $request ?

Non ! Haha… Il y a une petite subtilité à savoir ici.

La variable $request passé dans le Controller provient en réalité de la méthode capture() de la class Request de Laravel (dans le namespace Illuminate\Http\Request) qui elle-même fait appelle à la méthode statique createFromGlobals() de la class Request de Symfony :

// Class de Laravel : Illuminate\Http\Request

/**
 * Create a new Illuminate HTTP request from server variables.
 *
 * @return static
 */
public static function capture()
{
    static::enableHttpMethodParameterOverride();

    return static::createFromBase(SymfonyRequest::createFromGlobals());
}
// Class de Symfony : Symfony\Component\HttpFoundation\Request

/**
 * Creates a new request with values from PHP's super globals.
 *
 * @return static
 */
public static function createFromGlobals()
{
    $request = self::createRequestFromFactory($_GET, $_POST, [], $_COOKIE, $_FILES, $_SERVER);

    if (0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/x-www-form-urlencoded')
        && \in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), ['PUT', 'DELETE', 'PATCH'])
    ) {
        parse_str($request->getContent(), $data);
        $request->request = new ParameterBag($data);
    }

    return $request;
}

Hein ?! Mais on ne fait pas appelle à cette méthode capture pourtant ! Non ?

Et bien si ! Dans le fichier public/index.php Laravel initialise un objet qui capture les valeurs globales de la requête :

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);

Cet objet est ensuite passé dans le container de l’application via la méthode handle qui fait ensuite appelle à la méthode sendRequestThroughRouter() qui permet de passer la requête à travers le router (comme son joli nom l’indique ^^)

// dans la method sendRequestThroughRouter() de la class Kernel
// le namespace est Illuminate\Foundation\Http pour les curieux :)
$this->app->instance('request', $request);

Donc… Dans cet objet $request que l’on retrouve dans notre controller il y a…

L’ensemble des propriétés que l’on vient de voir dans le constructeur de la class Request de Symfony ! c’est à dire : $query$request$attributes$cookies$files$server .

Donc grâce à cet objet $request vous pouvez non seulement récupérer les inputs du formulaire envoyé ($_POST) ainsi que d’autres données tel que les cookies ($_COOKIE), les données de $_SERVER etc… mais aussi appliquer diverses méthodes à cet objet.

2. Récupérer les données

Maintenant voyons comment récupérer les données du formulaire grâce à cet objet $request.

$request->all() // pour récupérer tous les inputs du formulaire

Cela nous donnera un array :

array:5 [▼
    "_token" => "leTokenCsrf"
    "title" => "Le Monde comme volonté et comme représentation"
    "author" => "Arthur Schopenhauer"
    "price" => "19.99"
    "description" => "Œuvre majeure d'Arthur Schopenhauer regroupant 4 livres chacun traitant un thème essentiel : épistémologie, métaphysique, esthétique et éthique."
]

Et si nous voulons un champ en particulier, par exemple le champ author :

$request->input('author');

Cela nous retournera : “Arthur Schopenhauer”.

public function store(Request $request) {
    dd($request->all());
}

Une autre manière existe pour récupérer ces données : la façade Input. Qui était la méthode présenté par la documentation officielle de Laravel jusqu’à sa version 4.2. À partir de la version 5 c’est l’utilisation de l’objet $request qui est présentée dans la documentation. La façade Input n’y figurant plus, mais il est cependant toujours possible de l’utiliser.

Si vous vous demandez ce qu’est une Façade pas d’inquiétude nous verrons cela dans la partie 4 du cours qui portera sur des notions plus avancées.

Si vous désirez utiliser la façade Input voici comment faire les deux opérations que nous venons de voir :

Input::all(); // retourne l'ensemble des données du formulaire
Input::get('author') // retourne "Arthur Schopenhauer"

3. Les données de type fichier

Imaginons maintenant que nous voulons envoyer un fichier (ici une image qui correspondra à la couverture du livre en question). Rajoutons un champ de type file et faisons un die and dump pour voir comment nous récupérons les données de ce fichier :

<form action="{{ route('books.store') }}" method="POST" enctype="multipart/form-data">
    // les inputs précédents
<input type="file" name="cover">
    // le bouton submit
</form>
dd($request->all());

Voici ce que l’on récupère :

array:6 [▼
    "_token" => "m5llKkKDYA6T3mZJDtXNVBI7oDiMy9owohVxk8tC"
    "title" => "Le Monde comme volonté et comme représentation"
    "author" => "Arthur Schopenhauer"
    "price" => "19.99"
    "description" => "Œuvre majeure d'Arthur Schopenhauer regroupant 4 livres chacun traitant un thème essentiel : épistémologie, métaphysique, esthétique et éthique."
    "cover" => UploadedFile {#205 ▶}
]

On peut remarquer que pour notre input de type file on récupère un objet de UploadedFile, pour obtenir uniquement cet input il faut cette fois utiliser la méthode file() :

$request->file('cover');

Et tout comme pour les inputs classiques, la façade Input nous permet de faire exactement la même chose :

Input::file('cover');

Une autre façade peut être utile ici : la façade File qui a des méthodes intéressantes, en voici quelques unes :

$file = Input::file('cover');
\File::type($file); // retourne le type, ici : "file"
\File::mimeType($file); // retourne le mimeType, ici : "images/jpeg"
\File::size($file); // retourne la taille du fichier en bytes

La Class instanciée par la Façade File s’appelle Filesystem est se trouve dans le namespace Illuminate\Filesystem

Ici pas besoin d’ajouter le namespace de la façade (nous en reparlerons dans le chapitre des Façades).
Mais attention à bien écrire \File et non File.

Vous pouvez faire la même chose directement sur l’objet $request :

$file = $request->file('cover');
$file->getType();
$file->getMimeType();
$file->getSize();

À vous de voir ce que vous préférez, personnellement je trouve la façade File plus agréable.

Bien maintenance que nous savons récupérer les données d’un formulaire voyons comment procéder à des validations pour confirmer la bonne validité de ce que l’on souhaite entrer dans notre base de données.

Besoin d'une formation personalisée ?

Avis

4,9
Rated 4.9 out of 5
Excellent93%
Splendide !7%
Sympa0%
Sans plus0%
Pas terrible0%

Pas de titre

Rated 5 out of 5
7 mars 2024

super

hajar

Pas de titre

Rated 5 out of 5
21 juin 2023

Merci énormément je suis sur exciter à cause de ce cours

Kassi Patrick

Pas de titre

Rated 5 out of 5
10 mai 2023

Excellente formation

abdo maroc

Pas de titre

Rated 5 out of 5
7 mai 2023

Merci

Ranaivoson (c'est malgache)

Pas de titre

Rated 5 out of 5
18 avril 2023

Merci

Anthea