Statamic Peak

Article

Les pages d'erreurs avec Laravel et InertiaJS

Comment personnaliser les pages d'erreurs avec Laravel et InertiaJs ? Je vous explique tout !

Laravel gère automatiquement l'affichage de pages d'erreur. Elles sont détaillées en développement et contiennent des informations sur les causes de l'erreur. En production, elles sont très génériques et ne contiennent qu'un message, ce qui évite toute fuite de données.

En ajoutant Inertiajs, le fonctionnement par défaut de Laravel ne convient pas tout à fait. Comme les erreurs ne sont pas des réponses Inertia, elles sont ouvertes dans une modale, ce qui n'a pas trop de sens.

On va modifier le fonctionnement pour avoir une vraie redirection et afficher une page personnalisée !

Si c'est une technologie qui vous intéresse, je prépare un Compendium Laravel et j'ai publié plusieurs articles sur le sujet comme :

Afficher une réponse Inertia comme erreur Laravel

La documentation d'Inertia nous indique la démarche à suivre. On ajoute une fonction render à notre App\Exception\Handler.php, la même classe qu'on modifie si on veut ajouter un outil comme Sentry ou Flare.

use Throwable;
use Inertia\Inertia;

/**
 * Prepare exception for rendering.
 *
 * @param  \Throwable  $e
 * @return \Throwable
 */
public function render($request, Throwable $e)
{
    $response = parent::render($request, $e);

    if (!app()->environment(['local', 'testing']) && in_array($response->status(), [500, 503, 404, 403])) {
        return Inertia::render('Error', ['status' => $response->status()])
            ->toResponse($request)
            ->setStatusCode($response->status());
    } else if ($response->status() === 419) {
        return back()->with([
            'message' => __('The page expired, please try again.'),
        ]);
    }

    return $response;
}

Dans cette fonction, on récupère la réponse par défaut de Laravel, si on est en développement, on la renvoie simplement et on aura un affichage de la vue d'Ignition dans une modale. En production, on renvoie une réponse Inertia qu'on va pouvoir personnaliser.

Comme à chaque fois avec Inertia, on indique dans Inertia::render le nom du composant que l'on veut afficher. Dans notre exemple, il s'agit du fichier resources/js/Pages/Error.vue.

Ensuite, comme il s'agit d'une réponse Inertia classique et d'un composant Vue, on peut faire tout ce qu'on veut : passer des données du serveur en props, traduire le contenu, etc.

<template>
    <app-layout :public-site="true">
        <div v-if="status === 404">
            <div class="container">
                <div>
                    <div>
                        <h1>404</h1>
                        <h2>Vous êtes perdu... ?</h2>
                        <p>Ne vous inquiétez pas...<br/>
                            <strong>Nous pouvons tout de même vous aider à trouver une maison !</strong></p>
                        <a :href="route('find-a-home')" class="mt-4">Trouver une maison maintenant !</a>
                    </div>
                </div>
            </div>
        </div>
        <div v-else>
            <h1>noparse_b7f3919a99d4093361004e8fd25d5a1e</h1>
            <div>noparse_e976016c7fa0a88cf04d9d783cbd57e1</div>
        </div>
    </app-layout>
</template>

<script>
import AppLayout from "@/Layouts/AppLayout";
export default {
    components: {AppLayout},
    props: {
        status: Number,
    },
    computed: {
        title() {
            return {
                503: '503: Service Indisponible',
                500: '500: Erreur',
                403: '403: Accès refusé',
            }[this.status]
        },
        description() {
            return {
                503: "Désolé, nous sommes en train d'effectuer une maintenance. Revenez plus tard.",
                500: 'Oups, une erreur est survenue.',
                403: "Désolé, vous n'avez pas accès à cette page.",
            }[this.status]
        },
    },
}
</script>