Passer au contenu principal

Qu’est-ce que Wayfinder ?

Laravel Wayfinder est un paquet qui relie sans friction le back-end Laravel et le front-end TypeScript. Il génère automatiquement des fonctions TypeScript entièrement typées à partir des contrôleurs et des routes, ce qui permet d’appeler directement les endpoints Laravel comme des fonctions depuis le code front-end. Le hardcoding des URL, la gestion manuelle des paramètres de route, la synchronisation manuelle des changements back-end — tout cela devient inutile.
Wayfinder est en version bêta (actuellement v0.1.x). L’API pourrait changer avant la sortie de la v1.0.0. Tous les changements importants sont consignés dans le CHANGELOG.

Différences entre Ziggy et Wayfinder

Qu’est-ce que Ziggy ?

Ziggy est un helper de routes largement utilisé dans l’écosystème Laravel depuis de nombreuses années. Il expose les définitions de routes Laravel côté JavaScript et permet de générer les URL sous une forme comme route('posts.show', { id: 1 }).

Pourquoi a-t-il été remplacé par Wayfinder ?

Ziggy manipule les noms de routes et les paramètres sous forme de chaînes, ce qui limitait sa compatibilité avec TypeScript. Les fautes de frappe dans les noms de routes ou les noms de paramètres erronés ne provoquaient que des erreurs à l’exécution. Wayfinder est conçu selon une approche TypeScript-first et génère les méthodes de contrôleur comme des fonctions importables.
Critère de comparaisonZiggyWayfinder
Méthode de référence des routesroute('posts.show', { id: 1 })import { show } from "@/actions/..."
Sécurité de typeDéfinitions de types limitéesTypes TypeScript complets
Support IDEComplétion faibleComplétion et vérification de types complètes
Tree shakingToutes les routes incluses dans le bundleSeules les routes utilisées sont incluses
Moment de générationInjection au runtimeGénération statique au moment du build
Dans les starter kits Laravel basés sur Inertia (React, Vue, Svelte), Wayfinder est adopté par défaut.

Installation

1. Installez le paquet côté serveur avec Composer

composer require laravel/wayfinder

2. Installez le plugin Vite avec NPM

npm i -D @laravel/vite-plugin-wayfinder

3. Ajoutez le plugin à vite.config.js

import { wayfinder } from "@laravel/vite-plugin-wayfinder";
import { defineConfig } from "vite";
import laravel from "laravel-vite-plugin";

export default defineConfig({
    plugins: [
        laravel({
            input: ["resources/js/app.ts"],
            refresh: true,
        }),
        wayfinder(),
    ],
});
Lorsque vous ajoutez le plugin Vite, les fichiers TypeScript sont régénérés automatiquement chaque fois qu’un fichier PHP ou de routes change pendant que le serveur de développement est en cours d’exécution.

Génération des fichiers de définitions TypeScript

Générez les fichiers TypeScript avec la commande wayfinder:generate.
php artisan wayfinder:generate
Par défaut, trois répertoires sont générés sous resources/js.
resources/js/
├── actions/         # Fonctions d'actions de contrôleur
│   └── App/Http/Controllers/
│       └── PostController.ts
├── routes/          # Fonctions de routes nommées
│   └── post.ts
└── wayfinder/       # Fichiers de définitions de types
    └── types.ts
Les fichiers générés sont entièrement régénérés à chaque build ; il est donc recommandé de les ajouter à .gitignore. Excluez ensemble les trois répertoires wayfinder, actions et routes.
Pour modifier la destination de sortie, utilisez l’option --path.
php artisan wayfinder:generate --path=resources/js/api
Il est également possible de générer uniquement les actions de contrôleur ou uniquement les routes.
php artisan wayfinder:generate --skip-actions  # Génère uniquement les routes
php artisan wayfinder:generate --skip-routes   # Génère uniquement les actions

Utilisation de base

Import et utilisation d’une action

Voici un exemple qui génère l’URL correspondant à la méthode show de PostController.
import { show } from "@/actions/App/Http/Controllers/PostController";

show(1);
// { url: "/posts/1", method: "get" }
Si vous n’avez besoin que de l’URL, utilisez .url().
show.url(1); // "/posts/1"
Vous pouvez également spécifier une méthode HTTP particulière.
show.head(1); // { url: "/posts/1", method: "head" }

Passage de paramètres

Les fonctions Wayfinder acceptent des paramètres sous diverses formes.
import { update } from "@/actions/App/Http/Controllers/PostController";

// Paramètre unique
show(1);
show({ id: 1 });

// Plusieurs paramètres
update([1, 2]);
update({ post: 1, author: 2 });
update({ post: { id: 1 }, author: { id: 2 } });
Si un key binding est défini pour la route (/posts/{post:slug}), vous pouvez utiliser cette valeur.
// Si la route est /posts/{post:slug}
show("my-new-post");
show({ slug: "my-new-post" });

Import de tout un contrôleur

Vous pouvez également importer tout un contrôleur et appeler ses méthodes.
import PostController from "@/actions/App/Http/Controllers/PostController";

PostController.show(1);
PostController.index();
Importer un contrôleur entier empêche le tree shaking et inclut toutes les actions dans le bundle. Importer individuellement permet de conserver un bundle final plus petit.

Contrôleurs à action unique

Les contrôleurs à action unique (Invokable Controller) s’utilisent en appelant directement la fonction importée.
import StorePostController from "@/actions/App/Http/Controllers/StorePostController";

StorePostController(); // { url: "/posts", method: "post" }

Import de routes nommées

Pour accéder aux routes par leur nom, utilisez les fichiers sous routes/.
import { show } from "@/routes/post";

// Si le nom de route est `post.show`
show(1); // { url: "/posts/1", method: "get" }

Paramètres de requête

Toutes les fonctions Wayfinder acceptent l’option query pour ajouter des paramètres de requête.
import { show } from "@/actions/App/Http/Controllers/PostController";

show(1, { query: { page: 1, sort_by: "name" } });
// { url: "/posts/1?page=1&sort_by=name", method: "get" }
Pour fusionner avec les paramètres de requête de l’URL actuelle, utilisez mergeQuery.
// URL actuelle : /posts/1?page=1&sort_by=category&q=shirt

show.url(1, { mergeQuery: { page: 2, sort_by: "name" } });
// "/posts/1?page=2&sort_by=name&q=shirt"

// Pour supprimer un paramètre, spécifiez null
show.url(1, { mergeQuery: { sort_by: null } });
// "/posts/1?page=1&q=shirt"

Variantes de formulaire

Pour les formulaires HTML traditionnels, générez avec l’option --with-form et utilisez la variante .form.
php artisan wayfinder:generate --with-form
import { store, update } from "@/actions/App/Http/Controllers/PostController";

// Exemple React
const Page = () => (
    <form {...store.form()}>
        {/* <form action="/posts" method="post"> */}
    </form>
);

const EditPage = () => (
    <form {...update.form(1)}>
        {/* <form action="/posts/1?_method=PATCH" method="post"> */}
    </form>
);

Combinaison Inertia et Wayfinder

En combinant le helper de formulaire Inertia et Wayfinder, vous pouvez soumettre un formulaire sans écrire une seule chaîne d’URL.
import { useForm } from "@inertiajs/react";
import { store } from "@/actions/App/Http/Controllers/PostController";

const form = useForm({ name: "My Post" });

form.submit(store()); // Soumet sur POST /posts
Cela fonctionne de la même manière avec le composant Link.
import { Link } from "@inertiajs/react";
import { show } from "@/actions/App/Http/Controllers/PostController";

const Nav = () => (
    <Link href={show(1)}>Voir la publication</Link>
);

Adoption dans les starter kits

Lorsque vous créez un nouveau projet avec laravel new et sélectionnez React, Vue ou Svelte, vous obtenez une configuration où Wayfinder est automatiquement configuré. Les starter kits incluent ce qui suit.
  • Paquet Composer laravel/wayfinder
  • Paquet NPM @laravel/vite-plugin-wayfinder
  • Plugin déjà configuré dans vite.config.js
  • Répertoires générés déjà ajoutés à .gitignore
L’installation manuelle dans un projet existant suit la procédure présentée ci-dessus.

Gestion des noms de méthodes en conflit avec les mots réservés

Pour les méthodes de contrôleur portant le même nom que des mots réservés JavaScript comme delete ou import, un suffixe Method est ajouté.
// Si le contrôleur a une méthode delete
import { deleteMethod } from "@/actions/App/Http/Controllers/PostController";

deleteMethod(1); // { url: "/posts/1", method: "delete" }

État actuel (v0.1.x)

La version stable actuelle est fournie sur la branche v0.1.x. À la date de mars 2026, la dernière version est la v0.1.15.

Principal historique des versions v0.1.x

VersionContenu principal
v0.1.15Compatibilité Laravel 13, correction du crash des vues Blade
v0.1.13Amélioration de la compatibilité TypeScript strict pour les paramètres de requête
v0.1.7Prise en charge de la spécification côté front-end des paramètres URL par défaut
v0.1.6Ajout du plugin Vite
v0.1.5Support PHP 8.2, prise en charge des routes mises en cache
v0.1.0Version initiale

Fonctionnalités de nouvelle génération en développement sur la branche next

Sur la branche next, une prochaine version avec des fonctionnalités considérablement étendues par rapport à la v0.1.x actuelle est en développement.
La branche next peut être installée avec la contrainte dev-next, mais l’API est susceptible de changer considérablement. Son utilisation en production n’est pas recommandée.
composer require laravel/wayfinder:dev-next

Portée de génération TypeScript considérablement élargie

Alors que la v0.1.x ne cible que les routes et les actions de contrôleur, la prochaine version génère l’ensemble suivant en TypeScript.

Génération de types TypeScript pour les Form Requests

class StorePostRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'title'   => ['required', 'string', 'max:255'],
            'content' => ['required', 'string'],
            'tags'    => ['nullable', 'array'],
            'tags.*'  => ['string'],
        ];
    }
}
Le type suivant est généré à partir du Form Request ci-dessus.
export type Request = {
    title: string;
    content: string;
    tags?: string[] | null;
};

Génération de types pour les modèles Eloquent

class User extends Model
{
    protected $casts = [
        'email_verified_at' => 'datetime',
        'is_admin' => 'boolean',
    ];

    public function posts(): HasMany
    {
        return $this->hasMany(Post::class);
    }
}
À partir du modèle ci-dessus, les types sont générés dans types.d.ts.
export namespace App.Models {
    export type User = {
        id: number;
        name: string;
        email: string;
        email_verified_at: string | null;
        is_admin: boolean;
        posts: App.Models.Post[];
    };
}

Conversion des Enums PHP en TypeScript

enum PostStatus: string
{
    case Draft = 'draft';
    case Published = 'published';
    case Archived = 'archived';
}
Le type et les constantes sont tous deux générés.
// Définition de type (types.d.ts)
export namespace App.Enums {
    export type PostStatus = "draft" | "published" | "archived";
}

// Constantes (App/Enums/PostStatus.ts)
export const Draft = "draft";
export const Published = "published";
export const Archived = "archived";

export const PostStatus = { Draft, Published, Archived } as const;

Changement du répertoire de sortie

Dans la v0.1.x, la sortie était répartie dans les trois répertoires actions/, routes/ et wayfinder/, mais dans la prochaine version, tout est regroupé sous resources/js/wayfinder.
resources/js/wayfinder/
├── App/Http/Controllers/
│   └── PostController.ts    # Fonctions d'action (actions/ supprimé)
├── routes/
│   └── post.ts              # Routes nommées (identique)
├── broadcast-channels.ts    # Canaux de diffusion
├── broadcast-events.ts      # Événements de diffusion
└── types.d.ts               # Toutes les définitions de types (renommé depuis types.ts)

Principaux changements de la v0.1.x à next

  • Chemin d’import modifié de @/actions/... à @/wayfinder/...
  • Les flags --skip-actions, --skip-routes, --with-form sont supprimés et déplacés dans le fichier de configuration
  • types.ts renommé en types.d.ts

Résumé

Laravel Wayfinder repense selon une approche TypeScript-first la fonctionnalité offerte par Ziggy qui consiste à « référencer les routes Laravel depuis JavaScript ». Grâce à l’approche par import de fonctions générées, il apporte de grandes améliorations en matière de sécurité de type, de support IDE et de tree shaking. Même la v0.1.x actuelle offre déjà une référence typée aux routes et actions de contrôleur, et elle est adoptée par défaut dans les starter kits Laravel basés sur Inertia. La prochaine version en développement sur la branche next évoluera vers une infrastructure de sécurité de type plus complète, générant en TypeScript non seulement les Form Requests, les modèles Eloquent, les Enums, mais aussi les props de pages Inertia.

Laravel Wayfinder sur GitHub

Code source, CHANGELOG et Issues ici.

Vite Plugin Wayfinder

Détails des options de configuration du plugin Vite ici.
Dernière modification le 13 juillet 2026