fzed51 / migration
Outil en ligne de commande de migration de base de données en SQL pur (MySQL, SQLite, PostgreSQL)
Requires
- php: ^8.2
- ext-json: *
- ext-mbstring: *
- ext-pdo: *
- fzed51/pdo-helper: ^3.0
- symfony/console: ^7.4 || ^8.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.95
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^11.0
Suggests
- ext-pdo_mysql: pour les bases MySQL
- ext-pdo_pgsql: pour les bases PostgreSQL
- ext-pdo_sqlite: pour les bases SQLite
Provides
None
Conflicts
None
Replaces
None
- dev-main
- v3.1.1
- v3.1.0
- v3.0.0
- v2.0.0
- v1.4.5
- v1.4.4
- v1.4.3
- v1.4.1
- v1.4
- v1.3.7
- v1.3.6
- v1.3.5
- v1.3.4
- v1.3.3
- v1.3.2
- v1.3.1
- v1.3
- v1.2.4
- v1.2.3
- v1.2.2
- v1.2.1
- v1.1.3
- v1.1.2
- v1.1.1
- v1.1
- v1.0.2
- v1.0.1
- v1.0
- dev-release/v3.1.1
- dev-feat/symfony-console
- dev-ci/github-actions
- dev-copilot/fix-comment-cleanup-in-migrations
This package is auto-updated.
Last update: 2026-10-05 20:03:31 UTC
README
migration est un outil en ligne de commande qui applique des migrations de structure de base de données écrites en SQL pur. Il n'y a pas de DSL à apprendre : vous décrivez la connexion dans un fichier JSON, écrivez vos scripts SQL, puis lancez migrate run.
Bases supportées : MySQL, SQLite, PostgreSQL.
Cette documentation s'adresse aux humains comme aux agents (IA, scripts, CI). Les effets de bord, les préconditions et les codes de retour de chaque commande y sont décrits précisément.
- Prérequis
- Installation
- Démarrage rapide
- Commandes
- Configuration
- Écrire une migration
- Sorties et codes de retour
- Utilisation par un agent ou en CI
- Migration depuis la v2
- Développement
- Changelog, sécurité et licence
Prérequis
- PHP 8.2 ou supérieur, avec
ext-json,ext-mbstringetext-pdo - le driver PDO de votre base :
pdo_mysql,pdo_sqliteoupdo_pgsql
Installation
Le paquet est publié sur Packagist : https://packagist.org/packages/fzed51/migration.
composer require fzed51/migration
Le binaire est installé dans ./vendor/bin/migrate (sous Windows : vendor\bin\migrate.bat). Les exemples de cette documentation l'appellent simplement migrate.
Démarrage rapide
Exemple complet avec SQLite :
# 1. créer le fichier de configuration ./migration-config.json et le dossier ./db/migration ./vendor/bin/migrate init # 2. éditer ./migration-config.json (voir « Configuration »), par exemple : # "config_intern": { "provider": "sqlite", "name": "./db/data.sqlite" } # 3. pour SQLite uniquement : créer le fichier de base touch db/data.sqlite # 4. créer le dossier du provider : db/migration/sqlite/ ./vendor/bin/migrate provider sqlite # 5. créer un fichier de migration vide : db/migration/sqlite/YYYYMMDD-01-create_user.sql ./vendor/bin/migrate new create_user # 6. écrire le SQL dans ce fichier, puis appliquer les migrations en attente ./vendor/bin/migrate run
Lancé sans argument, migrate affiche une vue d'ensemble et la liste des commandes, sans rien modifier.
Commandes
| Commande | Rôle | Modifie la base ? | Idempotente ? |
|---|---|---|---|
migrate / migrate list |
Vue d'ensemble et liste des commandes | non | oui |
migrate help <commande> |
Aide détaillée d'une commande | non | oui |
migrate init |
Crée le fichier de configuration | non | non : échoue si le fichier existe |
migrate provider <name> |
Crée le dossier d'un provider | non | oui |
migrate new <name> |
Crée un fichier de migration vide par provider | non | non : crée un nouveau fichier à chaque appel |
migrate run |
Applique les migrations en attente | oui | oui : les fichiers déjà appliqués sont ignorés |
Option commune à init, provider, new et run :
| Option | Défaut | Description |
|---|---|---|
-c, --config=FILE |
./migration-config.json |
Chemin du fichier de configuration, relatif au répertoire courant |
Options globales fournies par Symfony Console : -h|--help, -V|--version, -q|--quiet, --silent, -v|-vv|-vvv, --ansi|--no-ansi, -n|--no-interaction.
migrate init
- Effet : écrit un modèle de configuration au chemin
--config, avecmigration_directory: ./db/migrationet les sectionsconfig_internetconfig_externà compléter. - Crée aussi le dossier
./db/migration, relatif au répertoire courant, s'il n'existe pas. - Échoue si le fichier existe déjà : il n'est jamais écrasé, et le dossier n'est pas créé.
- Ne contacte pas la base.
migrate provider <name>
- Arguments :
namevautmysql,sqlite,postgresoupostgresql.postgresqlest un alias qui crée le dossierpostgres. - Effet : crée
<migration_directory>/<name>/. - Préconditions : la configuration est valide et
migration_directoryexiste. - Idempotente : réussit aussi si le dossier existe déjà.
migrate new <name>
- Effet : crée un fichier vide
YYYYMMDD-NN-<name>.sqldans chaque dossier provider existant.YYYYMMDDest la date du jour.NNest le numéro d'ordre du jour : 01, 02…<name>est normalisé : minuscules, accents retirés, et chaque caractère non alphanumérique remplacé par_. Par exemple,"Création User"devientcreation_user.
- Échoue (code de retour différent de 0) s'il n'existe aucun dossier provider : lancez d'abord
migrate provider <name>.
migrate run
La base est modifiée. La commande :
- se connecte à la base décrite dans la configuration ;
- crée la table d'historique
migration_storysi elle n'existe pas ; - exécute, par ordre alphabétique, chaque fichier
<migration_directory>/<provider>/YYYYMMDD-NN-*.sqlabsent de l'historique, puis l'enregistre avec son checksum SHA1.
Points d'attention :
- Pas de transaction : si une requête échoue, les requêtes déjà exécutées du même fichier restent appliquées, et le fichier n'est pas enregistré.
- Pas de rollback : pour annuler une migration, écrivez-en une nouvelle.
- Ne modifiez jamais un fichier déjà appliqué : son checksum ne correspondrait plus et
runéchouerait avec le message « Intégrité compromise ». - Avec SQLite, le fichier de base doit exister avant le premier
run.
Configuration
Le fichier de configuration est un JSON (1 Mo maximum) :
{
"migration_directory": "./db/migration",
"config_intern": {
"provider": "sqlite",
"host": "",
"port": 0,
"name": "./db/data.sqlite",
"user": "",
"pass": ""
}
}
| Clé | Description |
|---|---|
migration_directory |
Dossier des migrations. Il doit exister et contient un sous-dossier par provider. |
config_intern.provider |
mysql, sqlite, postgres ou postgresql |
config_intern.host |
Hôte du serveur (MySQL, PostgreSQL) |
config_intern.port |
Port, en entier ; 0 ou absent : port par défaut (3306 MySQL, 5432 PostgreSQL) |
config_intern.name |
Nom de la base, ou chemin du fichier pour SQLite |
config_intern.user / pass |
Identifiants (MySQL, PostgreSQL) |
Exemples de config_intern :
// MySQL { "provider": "mysql", "host": "localhost", "name": "app", "user": "app", "pass": "secret" } // PostgreSQL { "provider": "postgres", "host": "localhost", "port": 5432, "name": "app", "user": "app", "pass": "secret" }
Réutiliser la configuration PHP d'un projet (config_extern)
Au lieu de dupliquer les identifiants, config_extern lit un fichier PHP qui retourne un tableau. Si config_extern.file pointe vers un fichier existant, cette section est utilisée à la place de config_intern.
{
"migration_directory": "./db/migration",
"config_extern": {
"file": "./config/settings.php",
"array_path": "settings/db",
"provider": "driver",
"host": "host",
"port": "port",
"name": "database",
"user": "username",
"pass": "password"
}
}
file: un fichier.phpsitué dans le répertoire du fichier de configuration (ou un sous-dossier).array_path: le chemin, séparé par/, vers le sous-tableau qui contient la connexion. Laissez-le vide si c'est la racine.provider,host,port,name,user,pass: le nom de la clé à lire dans ce sous-tableau.
Écrire une migration
- Emplacement :
<migration_directory>/<provider>/, par exempledb/migration/sqlite/. - Nom :
YYYYMMDD-NN-description.sql. Seuls les fichiers qui suivent ce motif sont pris en compte, dans l'ordre alphabétique. Utilisezmigrate newpour les créer. - Séparateur : une ligne commençant par
---sépare deux requêtes. - Commentaires : ce qui suit
--sur une ligne est ignoré. Le;final est optionnel.
CREATE TABLE user ( id INTEGER PRIMARY KEY ); --- -- une seconde requête CREATE TABLE entity ( id INTEGER PRIMARY KEY );
L'historique est conservé dans la table migration_story (colonnes file, content, checksum). Une migration appliquée ne doit plus être modifiée. Pour corriger, créez-en une nouvelle.
Sorties et codes de retour
| Canal | Contenu |
|---|---|
| stdout | Progression : migration : setup migration, migration : sqlite/20260925-01-create_user.sql, fichiers ou dossiers créés… |
| stderr | Message d'erreur (utilisez -v pour avoir la trace) |
| code de retour | 0 = succès, différent de 0 = échec |
Aucune commande ne pose de question interactive.
Par défaut, les erreurs PHP (warnings, notices) ne sont pas affichées mais envoyées au journal d'erreurs de PHP. Pour les afficher pendant un diagnostic, lancez la commande avec APP_ENV=development :
APP_ENV=development ./vendor/bin/migrate run -v
Utilisation par un agent ou en CI
Règles à suivre pour piloter l'outil automatiquement :
- Découvrir sans risque :
migrateetmigrate listne modifient rien. Une description lisible par une machine est disponible :./vendor/bin/migrate list --format=json # commandes, arguments, options et aides # (équivalent : migrate --help --format=json) ./vendor/bin/migrate help run --format=md # aide d'une commande en Markdown
- Lancer en mode non interactif et sans couleurs :
--no-interaction --no-ansi. - Toujours tester le code de retour : toute commande qui n'a pas pu faire son travail retourne un code différent de 0.
runest la seule commande qui modifie la base. Il n'y a ni transaction ni rollback.- Ne jamais éditer un fichier déjà appliqué. Pour corriger, créez une nouvelle migration avec
migrate new.
Check-list avant migrate run :
- le fichier de configuration pointe vers la bonne base (pas la production par erreur) ;
- les nouveaux fichiers sont dans
<migration_directory>/<provider>/et respectent le motifYYYYMMDD-NN-*.sql; - chaque requête est séparée par une ligne
---; - aucun fichier déjà appliqué n'a été modifié (
git diffsur le dossier de migration).
Migration depuis la v2
La v3 remplace les options par des sous-commandes (CLI basée sur symfony/console) et demande PHP 8.2 ou supérieur. La liste complète des changements est dans le CHANGELOG.
Étapes de mise à jour :
- Passez à PHP 8.2 ou supérieur si besoin.
- Mettez à jour la dépendance :
composer require fzed51/migration:^3.0. - Remplacez les appels dans vos scripts, votre CI et votre documentation à l'aide du tableau ci-dessous. Attention :
migrateseul n'applique plus les migrations, utilisezmigrate run. - Si vous utilisez
config_extern, vérifiez que le fichier PHP est dans le répertoire du fichier de configuration (ou un sous-dossier). - Lancez
migrate runsur une base de test : si un fichier déjà appliqué a été modifié depuis, la commande s'arrête sur « Intégrité compromise ».
| v2 | v3 |
|---|---|
migrate |
migrate run (migrate seul affiche maintenant l'aide) |
migrate -i |
migrate init |
migrate -n <nom> |
migrate new <nom> |
migrate -p <provider> |
migrate provider <provider> |
migrate -c <fichier> / -config_file <fichier> |
-c <fichier> / --config=<fichier> |
Autres changements de comportement :
- en cas d'erreur, le code de retour est différent de 0, et le message est écrit sur stderr ;
initcrée aussi le dossier./db/migration;newéchoue quand aucun dossier provider n'existe (la v2 affichait seulement un avertissement) ;runvérifie le checksum des fichiers déjà appliqués ;config_extern.filedoit être un fichier.phpplacé sous le répertoire du fichier de configuration ;--helpet--versionsont disponibles.
Développement
composer lint # composer validate + php-cs-fixer (PSR-12) + phpstan (niveau 6) composer fix # corrige le style (PSR-12) composer test # phpunit
La CI GitHub Actions lance composer lint, puis composer test sur chaque version de PHP supportée (8.2 à 8.5), ainsi qu'avec les dépendances les plus récentes autorisées par composer.json.
Changelog, sécurité et licence
- Historique des versions : CHANGELOG.md.
- Audit de sécurité et correctifs : SECURITY_REPORT.md.- Licence : MIT.