Passer au contenu principal

Introduction

Laravel 13 a été publié en mars 2026. Ce guide décrit la procédure de mise à niveau de Laravel 12.x vers 13.x.
Le temps estimé pour la mise à niveau est d’environ 10 minutes. Cependant, l’impact des changements de rupture sur votre application varie selon sa taille et les fonctionnalités utilisées.

Mise à niveau assistée par IA

Vous pouvez également automatiser la mise à niveau avec Laravel Boost. Boost est un serveur MCP de première partie qui fournit à votre assistant IA des invites de mise à niveau étape par étape. Après l’avoir installé dans une application Laravel 12, vous pouvez démarrer la mise à niveau vers Laravel 13 avec la commande slash /upgrade-laravel-v13 dans Claude Code, Cursor, OpenCode, Gemini et VS Code. Cette commande nécessite laravel/boost ^2.0. Même avec des outils IA qui ne prennent pas en charge les commandes slash, vous pouvez exécuter la même procédure de mise à niveau en référençant directement le fichier d’invite. Collez l’invite suivante telle quelle dans votre IA.
prompt
Chargez l'invite fournie par Laravel Boost et effectuez la mise à niveau de Laravel 12 vers 13.
https://raw.githubusercontent.com/laravel/boost/refs/heads/main/src/Mcp/Prompts/UpgradeLaravelv13/upgrade-laravel-v13.blade.php

- Répercutez les changements du squelette `laravel/laravel`. Consultez la branche 13.x, pas master.
- Ne modifiez pas `database/migrations/*_create_cache_table.php` directement, créez une nouvelle migration.
- Réglez `serialization` dans `config/session.php` sur `php`. `'serialization' => 'php'`
- Le changement le plus susceptible de provoquer des erreurs dans une application Laravel 13 est le changement de comportement du cache. Recherchez donc dans votre projet les emplacements où le cache est utilisé, et si l'autorisation ne pose pas de problème, mettez à jour `serializable_classes` dans config/cache.php pour les autoriser.

'serializable_classes' => [
    App\Data\CachedDashboardStats::class,
    App\Support\CachedPricingSnapshot::class,
    Illuminate\Support\Collection::class,
    Illuminate\Database\Eloquent\Collection::class,
],

Changements par niveau d’impact

Impact : élevé

  • Mise à jour des dépendances
  • Mise à jour de l’installateur Laravel
  • Prévention de la contrefaçon de requêtes (CSRF)

Impact : moyen

  • Configuration serializable_classes du cache
  • Configuration serialization de la session

Impact : faible

  • Préfixe de cache et nom du cookie de session
  • Sérialisation des collections de modèles
  • Container::call et valeurs par défaut de classes nullable
  • Priorité d’enregistrement des routes de domaine
  • Charge utile d’exception de l’événement JobAttempted
  • Liaison des callbacks extend de Manager
  • Requêtes DELETE MySQL (JOIN / ORDER BY / LIMIT)
  • Nom des vues de pagination Bootstrap
  • Génération du nom des tables pivots polymorphes
  • Renommage de propriété de l’événement QueueBusy
  • Réinitialisation entre tests des fabriques Str

Procédure de mise à niveau

Mise à jour des dépendances

Impact : élevé Mettez à jour les dépendances suivantes dans composer.json.
{
  "require": {
    "laravel/framework": "^13.0",
    "laravel/tinker": "^3.0"
  },
  "require-dev": {
    "phpunit/phpunit": "^12.0",
    "pestphp/pest": "^4.0"
  }
}
Si vous utilisez Laravel Boost, mettez-le également à jour.
{
  "require": {
    "laravel/boost": "^2.0"
  }
}
Après la mise à jour, installez les dépendances avec la commande suivante.
composer update

Mise à jour de l’installateur Laravel

Impact : élevé Si vous utilisez la CLI de l’installateur Laravel pour créer de nouvelles applications Laravel, mettez à jour vers la version compatible avec Laravel 13.x. Si vous l’avez installé avec composer global require :
composer global update laravel/installer
Si vous utilisez la version fournie avec Laravel Herd, mettez à jour Herd lui-même vers la dernière version.

Changements de rupture (Breaking Changes)

Sécurité

Prévention de la contrefaçon de requêtes

Impact : élevé Le middleware CSRF de Laravel a été renommé de VerifyCsrfToken en PreventRequestForgery. De plus, une vérification de l’origine de la requête à l’aide de l’en-tête Sec-Fetch-Site a été ajoutée. VerifyCsrfToken et ValidateCsrfToken restent en tant qu’alias dépréciés, mais toutes les références directes doivent être mises à jour vers PreventRequestForgery. Soyez particulièrement attentif si vous excluez le middleware dans les tests ou les définitions de routes.
use Illuminate\Foundation\Http\Middleware\PreventRequestForgery;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;

// Laravel <= 12.x
->withoutMiddleware([VerifyCsrfToken::class]);

// Laravel >= 13.x
->withoutMiddleware([PreventRequestForgery::class]);
preventRequestForgery(...) est également disponible dans l’API de configuration du middleware.

Cache

Impact : faible Les préfixes par défaut des clés de cache et Redis de Laravel utilisent désormais un suffixe séparé par des tirets. De plus, le nom par défaut du cookie de session utilise désormais Str::snake(...). De nombreuses applications ne sont pas affectées par ce changement, car elles définissent explicitement les valeurs dans les fichiers de configuration. Seules les applications qui s’appuient sur les paramètres de repli du framework sont concernées.
// Laravel <= 12.x
Str::slug((string) env('APP_NAME', 'laravel'), '_').'_cache_';
Str::slug((string) env('APP_NAME', 'laravel'), '_').'_database_';
Str::slug((string) env('APP_NAME', 'laravel'), '_').'_session';

// Laravel >= 13.x
Str::slug((string) env('APP_NAME', 'laravel')).'-cache-';
Str::slug((string) env('APP_NAME', 'laravel')).'-database-';
Str::snake((string) env('APP_NAME', 'laravel')).'_session';
Pour conserver le comportement précédent, définissez explicitement les valeurs dans le fichier .env.
CACHE_PREFIX=myapp_cache_
REDIS_PREFIX=myapp_database_
SESSION_COOKIE=myapp_session

Configuration serializable_classes du cache

Impact : moyen Une option serializable_classes a été ajoutée à la configuration par défaut de cache, avec false comme valeur par défaut. Cela prévient les attaques par chaîne de gadgets de désérialisation PHP en cas de fuite d’APP_KEY. Si votre application stocke intentionnellement des objets PHP dans le cache, vous devez lister explicitement les classes autorisées à être désérialisées.
// config/cache.php
'serializable_classes' => [
    App\Data\CachedDashboardStats::class,
    App\Support\CachedPricingSnapshot::class,
],
Si vous désérialisiez des objets de cache arbitraires, vous devez migrer vers une liste blanche de classes explicites ou vers des charges utiles de cache sans objet (comme des tableaux).

Configuration serialization de la session

Impact : moyen Le squelette de Laravel 13 (laravel/laravel) ajoute 'serialization' => 'json' dans config/session.php. Toutefois, la valeur par défaut interne du framework reste php.
Si vous appliquez les modifications du squelette telles quelles à l’aide d’un outil IA, 'serialization' => 'json' peut être ajouté à config/session.php. Ce changement modifie la méthode de sérialisation de la session, ce qui peut provoquer des erreurs dans les applications qui stockent des objets PHP en session.
Le guide officiel de mise à niveau ne mentionne pas ce changement de configuration. Cela signifie probablement qu’il n’est pas nécessaire de le modifier. Dans Laravel, certains changements ne sont parfois pas documentés dans le guide de mise à niveau, car ils n’ont pas d’impact lors d’une mise à niveau depuis la version précédente. Cela peut poser problème quelques années plus tard, lorsque l’on souhaite effectuer une mise à niveau et que l’on ne dispose plus des informations, d’où l’importance des enregistrements non officiels. Pour conserver le même comportement que dans Laravel 12 et versions antérieures, définissez explicitement 'serialization' => 'php'.
// config/session.php
'serialization' => 'php',
Si vous souhaitez activer la sérialisation JSON, vérifiez au préalable que vous ne stockez pas d’objets PHP en session.

Conteneur

Container::call et valeurs par défaut de classes nullable

Impact : faible Container::call respecte désormais les valeurs par défaut des paramètres de classe nullable lorsque aucun binding n’existe (ce qui correspond au comportement introduit dans Laravel 12 pour l’injection par constructeur).
$container->call(function (?Carbon $date = null) {
    return $date;
});

// Laravel <= 12.x : retourne une instance de Carbon
// Laravel >= 13.x : retourne null

Base de données

Requêtes DELETE MySQL

Impact : faible Laravel compile désormais des requêtes complètes DELETE ... JOIN avec ORDER BY et LIMIT selon la grammaire MySQL. Dans les versions précédentes, les clauses ORDER BY / LIMIT étaient parfois ignorées dans les requêtes DELETE avec JOIN. Dans Laravel 13, ces clauses sont incluses dans le SQL généré. En conséquence, une QueryException peut survenir sur certains moteurs de base de données qui ne prennent pas en charge cette syntaxe.

Eloquent

Génération du nom des tables pivots polymorphes

Impact : faible Lorsque le nom de table est deviné pour des modèles pivots polymorphes utilisant des classes de modèles pivots personnalisés, Laravel génère désormais des noms au pluriel. Si vous vous appuyiez sur les noms devinés au singulier auparavant, définissez explicitement le nom de la table dans le modèle pivot.
class RoleUser extends MorphPivot
{
    protected $table = 'role_user'; // spécification explicite
}

Sérialisation des collections de modèles

Impact : faible Lorsque les collections de modèles Eloquent sont sérialisées et restaurées (par exemple, dans les jobs mis en file d’attente), les relations chargées en eager sont désormais restaurées pour les modèles. Si votre code s’appuie sur l’absence de relations après la désérialisation, une correction est nécessaire.

File d’attente

Charge utile d’exception de l’événement JobAttempted

Impact : faible L’événement Illuminate\Queue\Events\JobAttempted expose désormais l’objet d’exception (ou null) via $exception, au lieu de l’ancienne propriété booléenne $exceptionOccurred.
// Laravel <= 12.x
if ($event->exceptionOccurred) {
    // une exception a été levée
}

// Laravel >= 13.x
if ($event->exception !== null) {
    // une exception a été levée
    $exception = $event->exception;
}

Renommage de propriété de l’événement QueueBusy

Impact : faible La propriété $connection de l’événement Illuminate\Queue\Events\QueueBusy a été renommée en $connectionName pour la cohérence avec les autres événements de file d’attente.
// Laravel <= 12.x
$event->connection;

// Laravel >= 13.x
$event->connectionName;

Routage

Priorité d’enregistrement des routes de domaine

Impact : faible Les routes avec un domaine explicite ont désormais la priorité sur les routes sans domaine lors de la correspondance de routes. Cela garantit que les routes de sous-domaine catch-all fonctionnent de manière cohérente, même lorsque des routes sans domaine sont enregistrées en premier.

Support

Liaison des callbacks extend de Manager

Impact : faible Les closures des pilotes personnalisés enregistrées via la méthode extend de Manager sont désormais liées à l’instance du Manager. Auparavant, si un autre objet (comme une instance de fournisseur de services) était référencé comme $this dans ces callbacks, vous devez maintenant déplacer la valeur dans la capture de la closure avec use (...).
// Laravel <= 12.x
Manager::extend('custom', function ($app) {
    return $this->createCustomDriver($app); // $this est le service provider
});

// Laravel >= 13.x
$provider = $this;
Manager::extend('custom', function ($app) use ($provider) {
    return $provider->createCustomDriver($app);
});

Réinitialisation entre tests des fabriques Str

Impact : faible Laravel réinitialise désormais les fabriques Str personnalisées lors du teardown des tests. Si vous vous appuyiez sur la persistance des fabriques UUID / ULID / chaîne aléatoire personnalisées entre les méthodes de test, veillez à les configurer dans chaque test concerné ou dans un hook de setup.

Vues

Nom des vues de pagination Bootstrap

Impact : faible Les noms des vues de pagination internes par défaut de Bootstrap 3 sont désormais explicites.
// Laravel <= 12.x
pagination::default
pagination::simple-default

// Laravel >= 13.x
pagination::bootstrap-3
pagination::simple-bootstrap-3
Si vous référencez directement les anciens noms de vues de pagination, mettez-les à jour.

Fonctionnalités dépréciées

FonctionnalitéAlternative
Middleware VerifyCsrfTokenPreventRequestForgery
Middleware ValidateCsrfTokenPreventRequestForgery
JobAttempted::$exceptionOccurredJobAttempted::$exception
QueueBusy::$connectionQueueBusy::$connectionName

Ajouts de contrats

Impact : très faible Concerne uniquement les cas d’implémentations personnalisées.

Contrat Dispatcher

La méthode dispatchAfterResponse($command, $handler = null) a été ajoutée au contrat Illuminate\Contracts\Bus\Dispatcher.

Contrat ResponseFactory

La signature eventStream a été ajoutée au contrat Illuminate\Contracts\Routing\ResponseFactory.

Contrat MustVerifyEmail

markEmailAsUnverified() a été ajouté au contrat Illuminate\Contracts\Auth\MustVerifyEmail.

Contrat Queue

Les méthodes suivantes d’inspection de la taille de la file d’attente ont été ajoutées au contrat Illuminate\Contracts\Queue\Queue (elles étaient auparavant déclarées uniquement dans les docblocks).
  • pendingSize
  • delayedSize
  • reservedSize
  • creationTimeOfOldestPendingJob

Contrats Store / Repository

Une méthode touch pour prolonger le TTL a été ajoutée aux contrats de cache.
// Illuminate\Contracts\Cache\Store
public function touch($key, $seconds);

Points forts des nouvelles fonctionnalités

Mise à niveau assistée par IA (Laravel Boost)

Laravel Boost est le serveur MCP officiel. Il s’intègre à votre éditeur IA et permet une mise à niveau semi-automatique via la commande /upgrade-laravel-v13.

Vérification de l’origine de la requête via l’en-tête Sec-Fetch-Site

Le middleware PreventRequestForgery effectue une vérification supplémentaire de l’origine à l’aide de l’en-tête Sec-Fetch-Site. La protection CSRF est ainsi renforcée.

Désérialisation sécurisée du cache

Grâce à la configuration serializable_classes, seules les classes autorisées sont désérialisées. La sécurité contre les attaques de désérialisation PHP est améliorée.

eventStream pour SSE (Server-Sent Events)

eventStream a été ajouté au contrat ResponseFactory, améliorant la prise en charge des Server-Sent Events.

Visibilité accrue de la file d’attente

Les méthodes pendingSize, delayedSize, reservedSize du contrat Queue permettent désormais de surveiller plus finement l’état de la file d’attente.

Problèmes courants de migration et solutions

Problème : les tests liés à CSRF échouent

Symptôme : les tests qui référencent VerifyCsrfToken échouent avec une erreur de classe introuvable. Solution : mettez à jour toutes les références vers PreventRequestForgery.
// Avant
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
->withoutMiddleware([VerifyCsrfToken::class]);

// Après
use Illuminate\Foundation\Http\Middleware\PreventRequestForgery;
->withoutMiddleware([PreventRequestForgery::class]);

Problème : impossible de restaurer un objet depuis le cache

Symptôme : les données récupérées depuis le cache sont null, ou une UnserializationFailedException est levée. Solution : ajoutez les classes utilisées à serializable_classes dans config/cache.php, ou convertissez les valeurs mises en cache en tableaux.
'serializable_classes' => [
    App\Models\User::class,
    App\Data\SomeData::class,
],

Problème : l’écouteur JobAttempted ne fonctionne pas

Symptôme : $event->exceptionOccurred renvoie null ou provoque une erreur non défini. Solution : modifiez en $event->exception !== null.
// Avant
if ($event->exceptionOccurred) { ... }

// Après
if ($event->exception !== null) { ... }

Problème : les sessions sont invalidées

Symptôme : les utilisateurs sont déconnectés après la mise à niveau. Solution : le nom par défaut du cookie de session a changé. Définissez explicitement SESSION_COOKIE dans .env pour conserver l’ancienne valeur.
SESSION_COOKIE=laravel_session

Problème : les clés de cache sont introuvables

Symptôme : le nombre de cache miss augmente après la mise à niveau. Solution : le préfixe de cache a changé. Définissez CACHE_PREFIX dans .env, ou videz le cache.
php artisan cache:clear

Ressources

Dernière modification le 13 juillet 2026