> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Guide de mise à niveau de Laravel 12 vers 13

> Explication de la procédure de mise à niveau de Laravel 12 vers Laravel 13, des changements de rupture, des fonctionnalités dépréciées et des points forts des nouvelles fonctionnalités.

## 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.

<Info>
  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.
</Info>

### Mise à niveau assistée par IA

Vous pouvez également automatiser la mise à niveau avec [Laravel Boost](https://github.com/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.

```text prompt theme={null}
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`.

```json theme={null}
{
  "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.

```json theme={null}
{
  "require": {
    "laravel/boost": "^2.0"
  }
}
```

Après la mise à jour, installez les dépendances avec la commande suivante.

```shell theme={null}
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` :

```shell theme={null}
composer global update laravel/installer
```

Si vous utilisez la version fournie avec [Laravel Herd](https://herd.laravel.com), 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.

```php theme={null}
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

#### Préfixe de cache et nom du cookie de session

**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.

```php theme={null}
// 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`.

```ini theme={null}
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.

```php theme={null}
// 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`.

<Warning>
  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.
</Warning>

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'`.

```php theme={null}
// 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).

```php theme={null}
$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.

```php theme={null}
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`.

```php theme={null}
// 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.

```php theme={null}
// 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 (...)`.

```php theme={null}
// 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.

```php theme={null}
// 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 `VerifyCsrfToken`       | `PreventRequestForgery`      |
| Middleware `ValidateCsrfToken`     | `PreventRequestForgery`      |
| `JobAttempted::$exceptionOccurred` | `JobAttempted::$exception`   |
| `QueueBusy::$connection`           | `QueueBusy::$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.

```php theme={null}
// 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`.

```php theme={null}
// 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.

```php theme={null}
'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`.

```php theme={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.

```ini theme={null}
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.

```shell theme={null}
php artisan cache:clear
```

***

## Ressources

* [Guide officiel de mise à niveau (anglais)](https://laravel.com/docs/13.x/upgrade)
* [Diff du dépôt laravel/laravel (12.x → 13.x)](https://github.com/laravel/laravel/compare/12.x...13.x)
* [Laravel Shift](https://laravelshift.com) — service communautaire d'automatisation des mises à niveau
* [Laravel Boost](https://github.com/laravel/boost) — serveur MCP pour la mise à niveau assistée par IA


## Related topics

- [Guide de mise à niveau de Laravel 11 à 12](/fr/blog/upgrade-11-to-12.md)
- [Mise à niveau de Laravel 8 vers 9](/fr/blog/upgrade-8-to-9.md)
- [Mise à niveau de Laravel 9 vers 10](/fr/blog/upgrade-9-to-10.md)
- [Mise à niveau de Laravel 10 à 11](/fr/blog/upgrade-10-to-11.md)
- [Les nouveautés de Laravel 13](/fr/blog/laravel-13-new-features.md)
