103 votes

Exécution d'une migration Laravel spécifique (fichier unique)

J'ai 5 migrations dans mon projet. Je veux seulement exécuter l'une de ces migrations. Est-il possible de transmettre le nom d'un seul fichier à la commande php artisan migrate ?

2voto

Ahmed Mabrouk Points 31

Il y a un moyen facile que je connais pour le faire qui ne peut être disponible que pour vous sur juste hôte local

  1. Modifier votre fichier de migration si nécessaire
  2. ouvrez votre phpMyAdmin ou tout ce que vous utilisez pour voir votre table de base de données
  3. trouvez la table désirée et supprimez-la
  4. trouvez la table des migrations et ouvrez-la
  5. dans cette table sous le champ de migration, trouvez le nom de la table désirée et supprimez sa ligne
  6. enfin, exécutez la commande php artisan migrate à partir de votre ligne de commande ou de votre terminal. cela ne migrera que les tables qui n'existent pas dans la table des migrations dans la base de données.

Cette méthode est complètement sûre et ne causera pas d'erreurs ou de problèmes même si elle semble être une façon non professionnelle, mais elle fonctionne parfaitement.

bonne chance

1voto

Vahid Montazer Points 106

J'ai le même problème. Copiez les codes de création de table dans le premier fichier de migration quelque chose comme ci-dessous:

  public function up()
    {
        Schema::create('posts', function(Blueprint $table){
            $table->increments('id');
            // Autres colonnes...
            $table->timestamps();
        });
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            // Autres colonnes...
            $table->softDeletes()->nullable();
        });
    }

Vous pouvez également changer (diminuer) le numéro de colonne batch dans la table migrations ;)

Ensuite, exécutez php artisan migrate.

0voto

Jan Schuermann Points 248

Si c'est juste pour des fins de test, voici comment je le fais :

Pour mon cas, j'ai plusieurs migrations, l'une d'elles contient les paramètres de l'application.

Pendant que je teste l'application et que toutes les migrations ne sont pas encore configurées, je les déplace simplement dans un nouveau dossier "future". Ce dossier ne sera pas touché par artisan et il exécutera uniquement la migration que vous souhaitez.

Un contournement un peu sale, mais ça fonctionne...

0voto

Lancez une exception dans une migration, si vous ne voulez pas l'appliquer, et cela arrêterait tout le processus de migration.

En utilisant cette approche, vous pouvez diviser votre ensemble de migrations en étapes.

0voto

Jan Bradáč Points 56

Pour ceux qui sont toujours intéressés, mise à jour de Laravel 5 : Laravel a implémenté l'option d'exécuter un seul fichier de migration à la fois (dans la version 5.7).

Vous pouvez maintenant exécuter ceci : php artisan migrate --path=/database/migrations/my_migration.php (comme répondu ici)

Parce que le Illuminate\Database\Migrations\Migrator::getMigrationFiles() contient maintenant ce code : return Str::endsWith($path, '.php') ? [$path] : $this->files->glob($path.'/*_*.php'); (voir le code source.)


Mais dans mon cas d'utilisation, je voulais en fait exécuter un ensemble de migrations en même temps, pas seulement une ou toutes.

Donc j'ai suivi la méthode Laravel et enregistré une implémentation différente du Migrator, qui décide quels fichiers utiliser :

/**
 * Un migrateur qui peut exécuter plusieurs migrations spécifiquement choisies.
 */
class MigrationsSetEnabledMigrator extends Migrator
{
    /**
     * @param Migrator $migrator
     */
    public function __construct(Migrator $migrator)
    {
        parent::__construct($migrator->repository, $migrator->resolver, $migrator->files);

        // Compatibilité avec les versions >= 5.8
        if (isset($migrator->events)) {
            $this->events = $migrator->events;
        }
    }

    /**
     * Obtenir tous les fichiers de migration dans un chemin donné.
     *
     * @param  string|array $paths
     * @return array
     */
    public function getMigrationFiles($paths)
    {
        return Collection::make($paths)->flatMap(function ($path) {
            return Str::endsWith($path, ']') ? $this->parseArrayOfPaths($path) :
                (Str::endsWith($path, '.php') ? [$path] : $this->files->glob($path . '/*_*.php'));
        })->filter()->sortBy(function ($file) {
            return $this->getMigrationName($file);
        })->values()->keyBy(function ($file) {
            return $this->getMigrationName($file);
        })->all();
    }

    public function parseArrayOfPaths($path)
    {
        $prefix = explode('[', $path)[0];
        $filePaths = explode('[', $path)[1];
        $filePaths = rtrim($filePaths, ']');

        return Collection::make(explode(',', $filePaths))->map(function ($filePath) use ($prefix) {
            return $prefix . $filePath;
        })->all();
    }
}

Nous devons l'enregistrer dans le conteneur en tant que 'migrator' (pour être accessible en tant que $app['migrator']), car c'est ainsi que la commande Migrate y accède lorsqu'elle-même est enregistrée dans l'IoC. Pour ce faire, nous mettons ce code dans un fournisseur de services (dans mon cas, c'est un DatabaseServiceProvider) :

    public function register()
    {
        $this->app->extend('migrator', function ($migrator, $app) {
            return new MultipleSpecificMigrationsEnabledMigrator($migrator);
        });

        // Nous réinitialisons la liaison 'command.migrate', qui utilise le migrator - pour 
        // forcer le rafraîchissement de l'instance migrator.
        $this->app->instance('command.migrate', null);
    }

Ensuite, vous pouvez exécuter ceci :

php artisan migrate --path=[database/migrations/my_migration.php,database/migrations/another_migration.php]

Remarquez les fichiers de migration multiples, séparés par une virgule.

Cela a été testé et fonctionne sous Laravel 5.4 et devrait être compatible avec Laravel 5.8.

Pourquoi ?

Pour ceux qui sont intéressés : le cas d'utilisation est de mettre à jour la version de la base de données avec ses données.

Imaginez, par exemple, que vous vouliez fusionner la rue et le numéro de maison de tous les utilisateurs dans une nouvelle colonne, appelons-la street_and_house. Et imaginez que vous vouliez le faire sur plusieurs installations de manière sûre et testée - vous créeriez probablement un script pour cela (dans mon cas, je crée des commandes de versionnement de données - des commandes artisan).

Pour effectuer une telle opération, vous devez d'abord charger les utilisateurs en mémoire ; puis exécuter les migrations pour supprimer les anciennes colonnes et ajouter la nouvelle ; et ensuite pour chaque utilisateur affecter street_and_house=$street . " " . $house_no et enregistrer les utilisateurs. (Je simplifie ici, mais vous pouvez certainement imaginer d'autres scénarios)

Et je ne veux pas compter sur le fait que je peux exécuter toutes les migrations à tout moment donné. Imaginez que vous vouliez le mettre à jour de disons 1.0.0 à 1.2.0 et qu'il y avait plusieurs lots de telles mises à jour - exécuter d'autres migrations pourrait casser vos données, car ces migrations doivent être gérées par leur propre commande de mise à jour dédiée. Par conséquent, je veux seulement exécuter les mises à jour sélectionnées connues avec lesquelles cette mise à jour sait comment travailler, puis effectuer des opérations sur les données, et ensuite éventuellement exécuter la prochaine commande de mise à jour des données. (Je veux être le plus défensif possible).

Pour y parvenir, j'ai besoin du mécanisme susmentionné et de définir un ensemble fixe de migrations à exécuter pour qu'une telle commande fonctionne.

_Remarque : j'aurais préféré utiliser un décorateur simple utilisant la méthode magique __call et éviter l'héritage (un mécanisme similaire à celui que Laravel utilise dans le \Illuminate\Database\Eloquent\Builder pour envelopper le \Illuminate\Database\Query\Builder), mais la MigrateCommand, malheureusement, exige une instance de Migrator dans son constructeur._


Note finale : je voulais poster cette réponse à la question Comment puis-je exécuter une migration spécifique dans Laravel, car elle est spécifique à Laravel 5. Mais je ne peux pas - car cette question est marquée comme un doublon de celle-ci (bien que celle-ci soit taguée comme Laravel 4).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X