Laravel 13 a été conçu pour rester une mise à jour relativement simple depuis Laravel 12. Le guide officiel annonce un temps estimé d’upgrade d’environ 10 minutes pour la majorité des projets, tout en documentant les points à vérifier selon les cas particuliers. Source officielle : https://laravel.com/docs/13.x/upgrade
Cet article résume ce qu’il faut réellement faire, dans quel ordre, et les changements à surveiller pour éviter les régressions.
1. Avant de commencer : cadrer l’upgrade
Avant toute modification, l’objectif est de réduire le risque.
Checklist recommandée
- créer une branche dédiée à l’upgrade
- s’assurer que les tests existent et passent
- vérifier la version de PHP
- sauvegarder les fichiers de configuration sensibles
- relire les dépendances maison qui étendent Laravel
Vérifications initiales
php -v
composer show laravel/framework
composer outdated
php artisan --version
Point de départ attendu
Laravel 13 exige PHP 8.3 minimum. Si votre environnement tourne encore sous PHP 8.2, il faut traiter cette étape avant le reste.
2. Mettre à jour les dépendances Composer
Le premier changement à appliquer se trouve dans composer.json.
Dépendances à mettre à jour
laravel/frameworkvers^13.0laravel/tinkervers^3.0phpunit/phpunitvers^12.0pestphp/pestvers^4.0
Ensuite :
composer update
Conseil pratique
Si votre projet dépend de packages communautaires sensibles à la version du framework, exécutez aussi :
composer why-not laravel/framework 13.0
Cela aide à repérer rapidement un package qui bloque la montée de version.
3. Mettre à jour l’installer Laravel si vous l’utilisez
Si vous utilisez l’outil CLI laravel new, pensez aussi à mettre à jour l’installer.
composer global update laravel/installer
Si vous passez par Laravel Herd, mettez simplement Herd à jour.
4. Gérer le changement le plus important : PreventRequestForgery
C’est le point de plus fort impact dans le guide officiel.
Le middleware CSRF VerifyCsrfToken a été renommé en PreventRequestForgery. Les anciens alias existent encore, mais les références directes doivent être mises à jour.
Où vérifier dans votre projet
Recherchez les occurrences de :
VerifyCsrfToken::classValidateCsrfToken::class- exclusions de middleware sur des routes
- helpers ou macros autour du middleware CSRF
Recherche rapide
grep -R "VerifyCsrfToken" app routes tests config
5. Vérifier la configuration du cache : serializable_classes
Laravel 13 ajoute par défaut une option de sécurité dans la config cache :
'serializable_classes' => false,
Cette mesure durcit le comportement de désérialisation pour limiter certains risques si APP_KEY fuit.
Quand cela peut casser
Si votre application met volontairement des objets PHP dans le cache, ils ne pourront plus être désérialisés librement.
Nouvelle approche recommandée
Déclarer explicitement les classes autorisées :
'serializable_classes' => [
App\Data\CachedDashboardStats::class,
App\Support\CachedPricingSnapshot::class,
],
Recommandation concrète
Dans la mesure du possible, préférez stocker des tableaux ou des payloads simples dans le cache plutôt que des objets riches.
Exemple :
Cache::put('dashboard.stats', [
'users' => 1250,
'sales' => 930,
'growth' => 12.4,
], now()->addMinutes(30));
6. Vérifier les préfixes cache, Redis et le nom du cookie de session
Le guide signale un changement faible mais potentiellement piégeux si vous dépendez des valeurs générées par défaut.
Ancien comportement
Str::slug((string) env('APP_NAME', 'laravel'), '_').'_cache_';
Str::slug((string) env('APP_NAME', 'laravel'), '_').'_database_';
Str::slug((string) env('APP_NAME', 'laravel'), '_').'_session';
Nouveau comportement
Str::slug((string) env('APP_NAME', 'laravel')).'-cache-';
Str::slug((string) env('APP_NAME', 'laravel')).'-database-';
Str::snake((string) env('APP_NAME', 'laravel')).'_session';
Quand agir
Si votre application repose sur les valeurs de fallback du framework, alors vos clés Redis / cache et le cookie de session peuvent changer après l’upgrade.
Solution simple
Fixer explicitement les valeurs dans .env :
CACHE_PREFIX=myapp_cache_
REDIS_PREFIX=myapp_database_
SESSION_COOKIE=myapp_session
7. Vérifier les listeners liés aux événements de queue
Deux changements méritent un passage rapide.
JobAttempted : la propriété change
Avant :
$event->exceptionOccurred;
Après :
$event->exception;
QueueBusy : renommage de propriété
Avant :
$event->connection;
Après :
$event->connectionName;
Action recommandée
Recherchez vos listeners ou observateurs personnalisés :
grep -R "exceptionOccurred\|QueueBusy\|connectionName\|connection" app
8. Contrôler les requêtes MySQL DELETE ... JOIN
Laravel 13 compile désormais plus complètement certaines requêtes DELETE ... JOIN, y compris avec ORDER BY et LIMIT.
Pourquoi c’est sensible
Dans les versions précédentes, certains morceaux pouvaient être ignorés silencieusement. Avec Laravel 13, ils sont inclus dans le SQL généré. Résultat : certains moteurs peuvent maintenant lever une QueryException.
Exemple à auditer
DB::table('posts')
->join('users', 'users.id', '=', 'posts.user_id')
->where('users.inactive', true)
->orderBy('posts.id')
->limit(100)
->delete();
Recommandation
Passez en revue les suppressions complexes si votre projet manipule des requêtes SQL sophistiquées côté MySQL / MariaDB.
9. Éviter l’instanciation imbriquée pendant le boot des modèles
Créer une instance d’un modèle pendant qu’il est encore en phase de boot n’est plus autorisé.
Exemple problématique
protected static function boot()
{
parent::boot();
(new static())->getTable();
}
À faire à la place
Déplacer cette logique hors du cycle de boot.
Par exemple :
public static function tableName(): string
{
return (new static())->getTable();
}
Puis l’appeler ailleurs que dans boot().
10. Vérifier les cas particuliers liés à la sérialisation Eloquent
Le guide signale que les collections Eloquent sérialisées puis restaurées récupèrent désormais aussi leurs relations eager-loaded.
Pourquoi c’est important
Si vous aviez du code qui partait du principe qu’après désérialisation certaines relations ne seraient pas présentes, ce comportement peut changer.
C’est surtout à tester dans :
- les jobs queue
- les notifications différées
- les pipelines asynchrones
11. Vérifier les classes personnalisées qui implémentent des contrats Laravel
Si votre application ou vos packages maison implémentent certains contrats Laravel, l’upgrade impose quelques ajustements.
Contrats concernés dans le guide
Illuminate\Contracts\Cache\Store→ ajout detouchIlluminate\Contracts\Bus\Dispatcher→ ajout dedispatchAfterResponseIlluminate\Contracts\Routing\ResponseFactory→ ajout deeventStreamIlluminate\Contracts\Auth\MustVerifyEmail→ ajout demarkEmailAsUnverifiedIlluminate\Contracts\Queue\Queue→ nouvelles méthodes d’inspection
Exemple pour un store de cache personnalisé
public function touch($key, $seconds)
{
// Étendre le TTL de l’élément sans réécrire sa valeur
}
Exemple pour un MustVerifyEmail custom
public function markEmailAsUnverified()
{
$this->forceFill([
'email_verified_at' => null,
])->save();
}
12. Penser aux tests : Str factories, Unicode, sujets mail
Quelques changements de faible impact peuvent casser des tests trop stricts.
Cas à vérifier
- réinitialisation des factories
Strentre les tests Js::fromutilise désormaisJSON_UNESCAPED_UNICODE- le sujet par défaut de réinitialisation de mot de passe change
Sujet mail
Avant :
Reset Password Notification
Après :
Reset your password
Action utile
Relancez toute la suite de tests et inspectez surtout :
- les snapshots
- les assertions de chaînes exactes
- les sorties JS sérialisées
- les tests mail / notifications
13. L’ordre conseillé pour une mise à jour propre
Voici un ordre simple et fiable.
Étape 1
Mettre PHP à jour vers 8.3 minimum.
Étape 2
Mettre à jour composer.json puis lancer :
composer update
Étape 3
Corriger les références à VerifyCsrfToken.
Étape 4
Vérifier la config cache, surtout serializable_classes et les préfixes.
Étape 5
Auditer les points sensibles :
- listeners de queue
- implémentations de contrats custom
Container::call- requêtes MySQL
DELETE ... JOIN - sérialisation Eloquent
Étape 6
Exécuter les tests :
php artisan test
ou avec Pest :
./vendor/bin/pest
Étape 7
Tester manuellement les parcours critiques :
- authentification
- session
- formulaires protégés CSRF
- jobs asynchrones
- cache
- notifications
- back-office
14. Peut-on automatiser la mise à jour ?
Oui. Le guide officiel mentionne deux pistes :
- Laravel Shift, service communautaire d’automatisation d’upgrade
- Laravel Boost, outil first-party orienté IA, avec la commande
/upgrade-laravel-v13
Cela peut accélérer le travail, mais ne dispense pas de relire les changements qui touchent votre code métier.
Conclusion
La mise à jour de Laravel 12 vers Laravel 13 est globalement simple, mais elle mérite une vraie vérification sur quelques points précis.
Les éléments à surveiller en priorité sont :
- les dépendances Composer
- PHP 8.3 minimum
PreventRequestForgery- la configuration cache et
serializable_classes - les extensions personnalisées de contrats Laravel
- les listeners queue et certains comportements SQL / Eloquent
Si votre projet est proprement testé, l’upgrade devrait rester rapide. Le plus important n’est pas seulement de “faire passer Composer”, mais de sécuriser le comportement réel de l’application après migration.
Cet article vous présente quelques nouveautés de la version 13 : Nouveautés majeures à retenir.
Liens officiels
- Upgrade Guide : https://laravel.com/docs/13.x/upgrade
- Release Notes : https://laravel.com/docs/13.x/releases