Skip to main content
Pour maintenir dans la durée un package qui utilise la base de données, il ne suffit pas de gérer la première installation : il faut aussi une procédure pour livrer les changements aux utilisateurs dont les tables existent déjà. Concevez la publication des migrations, leur exécution et leur historique d’exécution comme des traitements distincts. Cette page part des bases du développement de packages et analyse ServiceProvider, VendorPublishCommand et Migrator de Laravel 13. L’implémentation du framework citée correspond à v13.34.0.

Copier les fichiers ou les charger depuis le package ?

publishesMigrations() se contente d’enregistrer la source et la destination comme éléments publiables. Le démarrage du provider ne copie aucun fichier et n’exécute aucun SQL. À l’inverse, loadMigrationsFrom() enregistre un chemin de recherche auprès du Migrator. Les fichiers de ce chemin sont alors pris en compte par un migrate ordinaire, mais le simple démarrage du provider ne les exécute pas. Si l’utilisateur doit pouvoir ajuster les noms de tables ou les colonnes avant l’exécution, la publication est l’approche à envisager. Si le package gère lui-même le schéma et ne suppose pas que l’utilisateur modifie les fichiers, le chargement direct est aussi une option. Les deux exemples de provider ci-dessous sont des alternatives.
Évitez de publier une migration tout en la chargeant aussi directement. Si l’horodatage change lors de la publication, la source et la copie sont traitées comme deux entrées distinctes de l’historique d’exécution, et la même création de table risque d’être exécutée deux fois.

Implémenter la publication

Attribuez un tag propre au package pour que l’utilisateur puisse publier ces fichiers indépendamment des autres ressources.
Lors de la première installation, copiez les fichiers en indiquant le provider et le tag, vérifiez leur contenu, puis exécutez-les. Lorsque les deux sont précisés, Laravel sélectionne les éléments publiables de ce tag qui appartiennent à ce provider.

La modification de l’horodatage dépend de la configuration

La documentation officielle indique que l’horodatage des migrations est remplacé par la date et l’heure actuelles lors de la publication. Toutefois, l’implémentation de ServiceProvider::publishesMigrations() n’ajoute la source aux éléments dont l’horodatage doit être mis à jour que si database.migrations.update_date_on_publish est activé. La valeur de repli lors de la lecture de ce paramètre est false. Le fichier config/database.php de l’application standard de Laravel 13 contient le paramètre suivant. Pour une application qui a hérité d’une ancienne structure, vérifiez aussi que ce paramètre existe.
De plus, VendorPublishCommand réécrit la date lorsque le chemin réel correspond à une source enregistrée et que le nom de destination contient le format YYYY_MM_DD_HHMMSS_. En partant de l’heure de lancement de la commande, il ajoute une seconde pour chaque fichier concerné. Si le nom ne contient pas ce format, ce traitement n’ajoute aucune date.
La date après publication ci-dessus est donnée à titre d’illustration. Le nom de fichier réel dépend du moment de la publication.
La mise à jour de l’horodatage dépend à la fois de l’enregistrement effectué par le package et de la configuration de l’application qui l’utilise. Ne modifiez pas ce paramètre de manière uniforme depuis le provider du package : documentez plutôt ce prérequis dans la procédure d’installation. Si le cache de configuration est utilisé, il faut aussi le reconstruire après avoir modifié la configuration.

Republier ne signifie pas « ajouter uniquement ce qui n’a pas été exécuté »

vendor:publish ne consulte pas l’historique d’exécution de la base de données. En outre, dans le traitement de copie de v13.34.0, la vérification de l’existence d’un fichier porte sur la destination avant la modification de l’horodatage. Même pour la publication d’un répertoire, la commande vérifie d’abord si le même chemin relatif que la source existe dans la destination, puis réécrit la date. Par conséquent, si la date a changé lors de la première publication et qu’aucun fichier portant le même nom que la source n’existe côté application, publier à nouveau le même tag peut ajouter un fichier avec une autre date. Ne partez pas du principe que l’absence de --force empêche toujours les doublons.

L’état d’exécution est déterminé par le nom de fichier

Migrator::getMigrationName() renvoie le nom de base du fichier sans .php. Pour déterminer si une migration n’a pas encore été exécutée, ce nom est comparé à l’historique d’exécution. La décision ne repose pas sur le contenu PHP ni sur l’identité des noms de tables.
Ce sont deux noms de migration différents. Même si la première a été exécutée, cet historique seul ne fait pas considérer la seconde comme exécutée.
Ne relancez pas systématiquement la commande de publication destinée à la première installation à chaque mise à jour du package, et ne faites pas de --force une étape standard. Non seulement les modifications des fichiers publiés seraient écrasées, mais le changement de date pourrait aussi ajouter des traitements en double.

Implémenter le chargement direct

Si vous souhaitez que les migrations du package soient exécutées telles quelles, enregistrez un chemin de recherche. Avec cette approche, n’ajoutez pas de traitement publiant les mêmes fichiers.
loadMigrationsFrom() appelle path() lorsque le Migrator est résolu. Migrator::path() élimine les chemins de recherche en double, et getMigrationFiles() indexe les fichiers trouvés par nom de migration puis les trie selon ce nom. Lorsque l’utilisateur met à jour le package, les nouveaux fichiers sont pris en compte par le migrate suivant. Ne renommez pas les fichiers existants et ajoutez un nouveau fichier pour chaque nouveau changement de schéma. Pour éviter les collisions avec d’autres packages, incluez aussi le nom de la fonctionnalité, comme dans create_courier_deliveries_table. Des fichiers de même nom ont la même clé : ils ne sont pas exécutés indépendamment l’un de l’autre.
Passer de la publication au chargement direct ne se résume pas à réécrire le provider. Si l’historique d’exécution de l’utilisateur a été enregistré avec les noms attribués lors de la publication, ceux-ci ne correspondent pas aux noms d’origine côté package. Il faut une procédure de migration couvrant l’historique des utilisateurs existants, les fichiers publiés et les rollbacks.

Livrer des changements de schéma aux utilisateurs existants

Par exemple, pour ajouter un numéro de suivi à la table des livraisons, n’éditez pas le fichier create_courier_deliveries_table déjà publié : ajoutez un nouveau fichier dédié à ce changement. Modifier une migration de création existante n’appliquera pas ce changement chez les utilisateurs qui l’ont déjà exécutée.
database/migrations/2026_10_02_000000_add_tracking_code_to_courier_deliveries_table.php
Comme il s’agit d’un ajout à une table qui contient déjà des lignes, la colonne est ici nullable. Si vous devez la rendre obligatoire ou remplir les données existantes, concevez séparément cette procédure et son ordre d’exécution. Avec la publication, prévoyez une procédure de mise à jour qui compare les fichiers déjà publiés chez l’utilisateur et ne livre que les fichiers ajoutés dans cette version. Vous pouvez créer un tag de publication réservé aux nouveaux fichiers, mais si la mise à jour de la date est activée, la même prudence s’applique à l’exécution répétée de ce tag. Ne réduisez pas la procédure de mise à jour à la simple réexécution du tag de première installation. Avec le chargement direct, le code mis à jour détecte les nouveaux fichiers. Dans les deux cas, la simple présence d’un fichier ne modifie pas la base de données : indiquez donc clairement dans les notes de version qu’il faut exécuter les migrations.

Vérifications avant la publication d’une version

En plus des tests de base de données du package, vérifiez les procédures de publication et de mise à jour dans une application qui l’utilise. Charger directement les migrations dans les tests ne suffit pas à valider l’approche par publication, dans laquelle les noms de fichiers changent.
  • Une première installation sur une base vide crée les tables nécessaires.
  • Une mise à jour depuis la base et l’historique d’exécution d’une version précédente n’applique que les nouveaux changements.
  • La liste des fichiers après plusieurs exécutions de la même commande de publication a été vérifiée, et la procédure de mise à jour ne crée pas de doublons.
  • La procédure tient compte de l’activation ou non de la mise à jour de la date, ainsi que des modifications apportées aux fichiers publiés.
  • Le rollback des nouvelles migrations et leur ordre d’exécution par rapport aux autres migrations de l’application ont été vérifiés.

Pages associées

Migrations

Les bases de la définition du schéma, de l’historique d’exécution et des rollbacks.

Tester un package

Tester le service provider et la base de données d’un package.

Fusion et mise en cache de la configuration d'un package

Une procédure de mise à jour qui tient compte de la configuration de l’utilisateur et du cache de configuration.

Gestion de la compatibilité des versions

Relier les procédures de mise à jour et les changements de compatibilité à votre politique de publication.

Sources primaires consultées

Dernière modification le 2 octobre 2026