Passer au contenu principal

Introduction

Laravel 9 a été publié le 8 février 2022. Ce guide organise la procédure de mise à niveau de Laravel 8.x vers 9.x et les changements les plus impactants.
Le temps estimé pour la mise à niveau est d’environ 30 minutes. Cependant, la charge de travail peut augmenter selon l’utilisation de l’envoi d’e-mails, du stockage de fichiers, des casts personnalisés et des surcharges des classes principales du framework.

Mise à niveau automatisée avec Laravel Shift

Vous pouvez également automatiser la mise à niveau avec Laravel Shift. Shift aide à mettre à jour composer.json et les fichiers de configuration, ce qui en fait un bon point de départ pour vérifier les diffs.

Changements par niveau d’impact

Impact : élevé

  • Mise à jour des dépendances
  • Migration vers Flysystem 3.x
  • Migration vers Symfony Mailer

Impact : moyen

  • Méthodes firstOrNew / firstOrCreate / updateOrCreate de BelongsToMany
  • Comportement de Custom Casts avec null
  • Timeout par défaut du client HTTP
  • Ajout des PHP Return Types
  • Renommage du paramètre schema pour Postgres
  • Suppression de la méthode assertDeleted
  • Déplacement du répertoire lang
  • Modification de la règle de mot de passe
  • Modification des méthodes when / unless
  • Traitement des clés de tableau non validées dans la validation

Procédure de mise à niveau

Mise à jour des dépendances

Impact : élevé Laravel 9 nécessite PHP 8.0.2 ou supérieur. Commencez par revoir les dépendances dans composer.json.
{
  "require": {
    "php": "^8.0.2",
    "laravel/framework": "^9.0",
    "spatie/laravel-ignition": "^1.0"
  },
  "require-dev": {
    "nunomaduro/collision": "^6.1"
  }
}
De plus, les mises à jour suivantes peuvent être nécessaires selon votre application.
  • Supprimer facade/ignition et le remplacer par spatie/laravel-ignition:^1.0
  • Si vous utilisez pusher/pusher-php-server, mettre à jour vers ^5.0
  • Vérifier que les paquets tiers utilisés disposent d’une version compatible avec Laravel 9
  • Si vous utilisez le canal de notification Vonage, consulter également son guide de mise à niveau spécifique
Après la mise à jour, installez les dépendances.
composer update

Version requise de PHP

Impact : élevé Laravel 9 requiert PHP 8.0.2 ou supérieur. Alignez la version de PHP sur l’ensemble de vos environnements — CI, développement local et production — avant de poursuivre la mise à niveau.

Migration vers Symfony Mailer

Impact : élevé L’un des grands changements de Laravel 9 est la migration de SwiftMailer (dont la maintenance a pris fin en décembre 2021) vers Symfony Mailer. Les applications qui utilisent uniquement le classique Mail::to()->send() sont peu impactées, tandis qu’une vérification est nécessaire si vous manipulez directement l’API bas niveau de SwiftMailer.

Dépendances des pilotes

# À ajouter uniquement si vous utilisez Mailgun
composer require symfony/mailgun-mailer symfony/http-client

# Si vous utilisez Postmark, supprimez le paquet pour SwiftMailer et remplacez-le
composer remove wildbit/swiftmailer-postmark
composer require symfony/postmark-mailer symfony/http-client

De withSwiftMessage à withSymfonyMessage

// Laravel 8.x : basé sur SwiftMailer
$this->withSwiftMessage(function ($message) {
    $message->getHeaders()->addTextHeader('Custom-Header', 'Header Value');
});

// Laravel 9.x : basé sur Symfony Mailer
use Symfony\Component\Mime\Email;

$this->withSymfonyMessage(function (Email $message) {
    $message->getHeaders()->addTextHeader('Custom-Header', 'Header Value');
});
Les méthodes send, html, raw, plain de Illuminate\Mail\Mailer renvoient désormais Illuminate\Mail\SentMessage au lieu de void. De plus, la propriété message de l’événement MessageSent contient désormais Symfony\Component\Mime\Email au lieu de Swift_Message.

Révision de la configuration SMTP

Dans Symfony Mailer, l’option stream pour SMTP a été supprimée, et les options prises en charge sont déplacées au niveau supérieur.
return [
    'mailers' => [
        'smtp' => [
            // Configuration Laravel 8.x
            'stream' => [
                'ssl' => [
                    'verify_peer' => false,
                ],
            ],

            // Configuration Laravel 9.x
            'verify_peer' => false,
        ],
    ],
];
La configuration explicite de auth_mode n’est plus nécessaire. Il est plus sûr d’orienter votre workflow vers une validation des adresses e-mail invalides avant l’envoi, plutôt que de tenter de les récupérer après.

Migration vers Flysystem 3.x

Impact : élevé Laravel 9 met à jour l’implémentation interne de la façade Storage de Flysystem 1.x vers 3.x. Les méthodes de manipulation de fichiers restent aussi compatibles que possible, mais il existe des différences autour des exceptions, des valeurs de retour et de l’enregistrement des adaptateurs.

Installation supplémentaire des pilotes

# Pilote Amazon S3
composer require -W league/flysystem-aws-s3-v3 "^3.0"

# Pilote FTP
composer require league/flysystem-ftp "^3.0"

# Pilote SFTP
composer require league/flysystem-sftp-v3 "^3.0"

Principaux changements de comportement de Storage

  • put / write / writeStream écrasent les fichiers existants par défaut
  • En cas d’échec d’écriture, false est retourné au lieu d’une exception
  • La lecture d’un fichier inexistant renvoie null au lieu d’une exception
  • delete sur un fichier inexistant renvoie true
  • L’adaptateur mis en cache a été supprimé ; vous pouvez supprimer la clé cache dans la configuration disk
Si vous souhaitez conserver le comportement précédent (exception en cas d’échec d’écriture), activez l’option throw.
return [
    'disks' => [
        'public' => [
            'driver' => 'local',
            // À activer uniquement si vous voulez lever une exception en cas d'échec d'écriture
            'throw' => true,
        ],
    ],
];
Si vous enregistrez des pilotes de système de fichiers personnalisés, ajustez le callback de Storage::extend() pour qu’il retourne directement une instance de Illuminate\Filesystem\FilesystemAdapter.

firstOrNew / firstOrCreate / updateOrCreate de BelongsToMany

Impact : moyen Dans Laravel 8, le tableau d’attributs passé en premier argument à ces méthodes était comparé à la table intermédiaire. Dans Laravel 9, il est comparé à la table du modèle associé.
// Recherche et met à jour name sur la table du modèle associé
$user->roles()->updateOrCreate([
    'name' => 'Administrator',
]);
De plus, firstOrCreate accepte désormais un deuxième argument $values, alignant son comportement sur celui des autres relations.
// Fusionne created_by uniquement lors de la création
$user->roles()->firstOrCreate([
    'name' => 'Administrator',
], [
    'created_by' => $user->id,
]);

Custom Casts et null

Impact : moyen Dans Laravel 9, la méthode set d’un custom cast est appelée même lorsque null est affecté à l’attribut casté. Les casts qui ne prévoient pas null peuvent lever une exception après la mise à niveau.
public function set($model, $key, $value, $attributes)
{
    // Dans Laravel 9, null peut être passé
    if ($value === null) {
        return [
            'address_line_one' => null,
            'address_line_two' => null,
        ];
    }

    if (! $value instanceof AddressModel) {
        throw new InvalidArgumentException('Veuillez passer un AddressModel.');
    }

    return [
        'address_line_one' => $value->lineOne,
        'address_line_two' => $value->lineTwo,
    ];
}

Timeout par défaut du client HTTP

Impact : moyen Le timeout par défaut du client HTTP est désormais de 30 secondes. Auparavant, il pouvait attendre indéfiniment.
use Illuminate\Support\Facades\Http;

// Prolonger le timeout individuellement pour les appels d'API plus longs
$response = Http::timeout(120)->get('https://example.com/api/status');

Ajout des PHP Return Types

Impact : moyen Dans Laravel 9, des types de retour ont été ajoutés aux différentes classes principales pour respecter les exigences de PHP et de Symfony. Si vous surchargez offsetGet, offsetSet, jsonSerialize, open, read, etc. dans des classes qui héritent des classes principales de Laravel, ajoutez les mêmes types de retour à vos propres implémentations.
// Alignez le type de retour lors de la surcharge des classes principales
public function offsetGet($key): mixed
{
    return parent::offsetGet($key);
}

Renommage du paramètre schema pour Postgres

Impact : moyen Si vous configurez le search path sur une connexion Postgres, modifiez le nom de la clé de schema en search_path dans config/database.php.
return [
    'pgsql' => [
        // Laravel 8.x
        'schema' => 'public',

        // Laravel 9.x
        'search_path' => 'public',
    ],
];

De assertDeleted à assertModelMissing

Impact : moyen assertDeleted, utilisé pour vérifier la suppression d’un modèle, doit être remplacé par assertModelMissing.
// Avant
$this->assertDeleted($user);

// Après
$this->assertModelMissing($user);

Déplacement du répertoire lang

Impact : moyen Dans les nouvelles applications Laravel 9, les fichiers de langue sont placés à la racine du projet dans lang, et non plus dans resources/lang. Cela a peu d’impact si vous vous contentez de faire tourner votre application existante, mais vérifiez cela si vous vous alignez sur le nouveau squelette ou si vous publiez des fichiers de traduction dans un paquet.
// Utilisez langPath() pour déterminer la destination de publication au lieu d'un chemin fixe
$this->publishes([
    __DIR__.'/../lang' => app()->langPath('vendor/package-name'),
]);

Modification de la règle de mot de passe

Impact : moyen La règle password, qui vérifie que la valeur correspond au mot de passe de l’utilisateur actuellement connecté, a été renommée en current_password.
// Avant
'password' => ['required', 'password'],

// Après
'password' => ['required', 'current_password'],

Modification des méthodes when / unless

Impact : moyen Dans Laravel 8, lorsque vous passiez une closure à when ou unless, la closure elle-même était évaluée comme truthy, ce qui pouvait entraîner l’exécution involontaire de la branche conditionnelle. Dans Laravel 9, la closure est exécutée et sa valeur de retour est utilisée comme condition.
$collection->when(function ($collection) {
    // La valeur retournée ici est évaluée comme condition
    return false;
}, function ($collection) {
    // false a été retourné, donc ce traitement n'est pas exécuté
    $collection->merge([1, 2, 3]);
});

Traitement des clés de tableau non validées

Impact : moyen Dans Laravel 9, validated() exclut toujours les clés de tableau non validées du tableau qu’elle retourne. Pour conserver le comportement compatible de Laravel 8, appelez explicitement includeUnvalidatedArrayKeys().
use Illuminate\Support\Facades\Validator;

public function boot()
{
    // À activer uniquement si vous souhaitez retrouver le comportement de Laravel 8
    Validator::includeUnvalidatedArrayKeys();
}

Résumé

La mise à niveau de Laravel 8 vers 9 se concentre sur la mise à jour vers PHP 8.0.2, la migration vers Symfony Mailer et la compatibilité avec Flysystem 3.x. En inspectant d’abord l’envoi d’e-mails, le stockage, les casts personnalisés et les helpers de test, vous limiterez les problèmes après la mise à niveau.
ChangementImpactAction
PHP 8.0.2 / laravel/framework:^9.0élevéMettre à jour composer.json et l’environnement d’exécution
Migration vers Symfony MailerélevéVérifier les API basées sur SwiftMailer et la configuration mail
Flysystem 3.xélevéVérifier les valeurs de retour, exceptions et dépendances de pilotes de Storage
Méthodes upsert de BelongsToManymoyenVérifier que la cible de recherche est désormais la table du modèle associé
Custom Casts et nullmoyenCorriger set() pour qu’elle ne casse pas en recevant null
Timeout de 30 secondes du client HTTPmoyenSpécifier timeout() uniquement pour les requêtes nécessaires
Suppression de assertDeletedmoyenRemplacer par assertModelMissing()
Déplacement du répertoire langmoyenRemplacer les références par chemin fixe par app()->langPath()
Modification de la règle passwordmoyenMettre à jour vers current_password
Exclusion des clés de tableau non validéesmoyenN’utiliser includeUnvalidatedArrayKeys() qu’en cas de besoin

Ressources

Dernière modification le 13 juillet 2026