Как запустить миграцию laravel и сеялку DB за исключением одного

У меня есть много файлов миграции и сеялки для запуска, хотя мне нужно будет запускать все файлы, но в настоящее время мне нужно пропустить одну миграцию и сеялку.

Как я могу пропустить один файл из команды laravel migration и db seeder.

Я не хочу удалять файлы из папки миграции или семян, чтобы пропустить файл.

Ответ 1

Laravel не дает вам метод по умолчанию для этого. Однако вы можете создать свои собственные консольные команды и сеялку для ее достижения.
Скажем, у вас есть этот класс по умолчанию DatabaseSeeder:

class DatabaseSeeder extends Seeder
{
    public function run()
    {
        $this->call(ExampleTableSeeder::class);
        $this->call(UserSamplesTableSeeder::class);
    }
}

Цель состоит в том, чтобы создать новую команду, переопределяющую "db: seed" и передать новый параметр "исключить" в класс DatabaseSeeder.

Это последний код, который я создал на моем примере Laravel 5.2, и попробовал:

Команда, добавив в приложение/Консоль/Команды, не забудьте обновить свой Kernel.php:

namespace App\Console\Commands;
use Illuminate\Console\Command;
class SeedExcept extends Command
{
    protected $signature = 'db:seed-except {--except=class name to jump}';
    protected $description = 'Seed all except one';
    public function handle()
    {
        $except = $this->option('except');
        $seeder = new \DatabaseSeeder($except);
        $seeder->run();
    }
}

DatabaseSeeder

use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
    protected $except;

    public function __construct($except = null) {
        $this->except = $except;
    }

    public function call($class)
    {
        if ($class != $this->except)
        {
            echo "calling $class \n";
            //parent::call($class);  // uncomment this to execute after tests
        }
    }

    public function run()
    {
        $this->call(ExampleTableSeeder::class);
        $this->call(UserSamplesTableSeeder::class);
    }
}

Это код, вы обнаружите, что я прокомментировал строку, которая вызывает семя, и добавила эхо для целей тестирования.

Выполнение этой команды:

php artisan db: seed-except

предоставит вам:

вызов ExampleTableSeeder
вызов UserSamplesTableSeeder

Однако добавление "except":

php artisan db: seed-except --except = ExampleTableSeeder

предоставит вам

вызов UserSamplesTableSeeder

Это перекрывает метод call по умолчанию вашего класса DatabaseSeeder и вызывает родителя, только если имя класса не указано в переменной $except. Переменная заполняется пользовательской командой SeedExcept.

Что касается миграции, вещь похожа, но немного сложнее.

Я не могу дать вам проверенный код для этого, но дело в том, что:

  • Вы создаете migrate-except команды, который переопределяет MigrateCommand класс (пространство имена Осветите\Database\Console\Миграция, расположенные в поставщике/Laravel/рамочный/SRC/Осветите/базы данных/консоль/Перемещение/MigrateCommand.php).
  • кнопка MigrateCommand занимает Migrator объект (пространство имен Осветите\базы данных\Миграция, путь поставщик/Laravel/рамки/SRC/Осветите/База данных/Перемещение/Migrator.php) в конструкторе (вводится через IoC). Класс Migrator владеет логикой, которая считывает все миграции внутри папки и выполняет ее. Эта логика находится внутри метода run()
  • создайте подкласс Migrator, например MyMigrator, и переопределите метод run(), чтобы пропустить файлы, переданные с помощью специальной опции
  • переопределите метод __construct() вашего MigrateExceptCommand и передайте MyMigrator: public function __construct(MyMigrator $migrator)

Если у меня есть время, я добавлю код для примера до того, как баунти закончится

ИЗМЕНИТЬ как и было обещано, вот пример миграции:

MyMigrator класс, расширяет Migrator и содержит логику для пропуска файлов:

namespace App\Helpers;
use Illuminate\Database\Migrations\Migrator;
class MyMigrator extends Migrator
{
    public $except = null;

    // run() method copied from it superclass adding the skip logic
    public function run($path, array $options = [])
    {
        $this->notes = [];

        $files = $this->getMigrationFiles($path);

        // skip logic
        // remove file from array
        if (isset($this->except))
        {
            $index = array_search($this->except,$files);
            if($index !== FALSE){
                unset($files[$index]);
            }
        }
        var_dump($files); // debug

        $ran = $this->repository->getRan();
        $migrations = array_diff($files, $ran);
        $this->requireFiles($path, $migrations);

        //$this->runMigrationList($migrations, $options);  // commented for debugging purposes
    }
}

Пользовательская команда MigrateExcept

namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Database\Console\Migrations\MigrateCommand;
use App\Helpers\MyMigrator;
use Illuminate\Database\Migrations\Migrator;
use Symfony\Component\Console\Input\InputOption;

class MigrateExcept extends MigrateCommand
{
    protected $name = 'migrate-except'; 

    public function __construct(MyMigrator $migrator)
    {   
        parent::__construct($migrator);
    }

    public function fire()
    {
        // set the "except" param, containing the name of the file to skip, on our custom migrator
        $this->migrator->except = $this->option('except');
        parent::fire();
    }

    // add the 'except' option to the command
    protected function getOptions()
    {
        return [
            ['database', null, InputOption::VALUE_OPTIONAL, 'The database connection to use.'],

            ['force', null, InputOption::VALUE_NONE, 'Force the operation to run when in production.'],

            ['path', null, InputOption::VALUE_OPTIONAL, 'The path of migrations files to be executed.'],

            ['pretend', null, InputOption::VALUE_NONE, 'Dump the SQL queries that would be run.'],

            ['seed', null, InputOption::VALUE_NONE, 'Indicates if the seed task should be re-run.'],

            ['step', null, InputOption::VALUE_NONE, 'Force the migrations to be run so they can be rolled back individually.'],

            ['except', null, InputOption::VALUE_OPTIONAL, 'Files to jump'],
        ];
    }
}

Наконец, вам нужно добавить это к поставщику услуг, чтобы разрешить Laravel IoC зависимости

namespace App\Providers;
use App\Helpers\MyMigrator;
use App\Console\Commands\MigrateExcept;


class CustomServiceProvider extends ServiceProvider
{
    public function boot()
    {
        parent::boot($events);

        $this->app->bind('Illuminate\Database\Migrations\MigrationRepositoryInterface', 'migration.repository');
        $this->app->bind('Illuminate\Database\ConnectionResolverInterface', 'Illuminate\Database\DatabaseManager');

        $this->app->singleton('MyMigrator', function ($app) {
            $repository = $app['migration.repository'];
            return new MyMigrator($repository, $app['db'], $app['files']);
        });
    }
}

Не забудьте добавить Commands\MigrateExcept::class в Kernel.php

Теперь, если вы выполните

php artisan migrate-except

у вас есть:

array(70) {
  [0] =>
  string(43) "2014_04_24_110151_create_oauth_scopes_table"
  [1] =>
  string(43) "2014_04_24_110304_create_oauth_grants_table"
  [2] =>
  string(49) "2014_04_24_110403_create_oauth_grant_scopes_table"
  ...

но добавив параметр except:

php artisan migrate-except --except = 2014_04_24_110151_create_oauth_scopes_table

array(69) {
  [1] =>
  string(43) "2014_04_24_110304_create_oauth_grants_table"
  [2] =>
  string(49) "2014_04_24_110403_create_oauth_grant_scopes_table"

Итак, recap:

  • мы создаем пользовательскую команду migrate-except, класс MigrateExcept, расширяя MigrateCommand
  • мы создаем собственный класс migrator, MyMigrator, расширяющий поведение стандартного Migrator
  • когда MigrateExcept является fire(), передайте имя файла, чтобы перейти к нашему MyMigrator классу
  • MyMigrator переопределяет метод run() Migrator и пропускает пройденную миграцию
  • Подробнее: поскольку нам нужно проинструктировать Laurvel IoC о новых созданных классах, чтобы он мог правильно их вводить, мы создаем поставщика услуг

Код протестирован, поэтому он должен корректно работать на Laravel 5.2 (надеясь, что cut & paste работает правильно:-)... если кто-то сомневается, оставляйте комментарий

Ответ 2

Пропуск семян очень прост, миграции не так много. Чтобы пропустить семя, удалите следующее из класса DatabaseSeeder.

$this->call(TableYouDontWantToSeed::class);

Для миграций Есть три способа сделать это:

  • Поместите класс, который вы не хотите переносить в другую папку.
  • Вставьте свои миграции в базу данных вручную (разработан Bindesh Pandya).
  • Переименуйте файл, который вы не хотите переносить, на что-то вроде UsersTableMigration.dud.

Надеюсь, что это поможет

Ответ 3

Я также столкнулся с той же проблемой в своем проекте, но после долгого времени траты в R и D я обнаружил, что Laravel не предоставляет никакого способа сделать это с помощью миграции и посева, но у вас есть 2 способа сделать это.

1) вы сэкономите много времени, просто поместив их в разные папки.  Теоретически вы можете создать свою собственную команду artisan, которая делает то, что  вы хотите, или подделывает его, создавая каталоги, перемещая файлы и запуская  php artisan migrate.

Для сеялок просто сделайте сеялку и позвоните другим сеялкам, из которых вы хотите бежать. Тогда просто укажите, какую сеялку вы хотите запустить. Попробуйте php artisan db:seed --help для получения более подробной информации.

2) вы можете создать таблицу вручную (которая имеет то же имя, что и таблица миграции, создающая в вас db) и вставить значения миграции, подобные этой

insert into migrations(migration, batch) values('2015_12_08_134409_create_tables_script',1);

поэтому команда migrate не создаст таблицу, которая уже существует в таблице миграции.

Ответ 4

Если вы хотите просто пропустить (но сохранить) миграцию и сеялку:

  • Переименуйте перенос, удалив расширение .php: mv your_migration_file.php your_migration_file
  • Перейдите к: DatabaseSeeder.php и закомментируйте строку с нежелательной сеялкой: //$this->call('YourSeeder');.
  • Выполнить: php artisan migrate --seed
  • Выполните ниже sql-запрос на db (будьте осторожны, должно быть имя файла миграции WITHOUT) (это предотвратит миграцию artisan для выполнения файла your_migration_file в будущем):

    INSERT INTO migrations (migration, batch) ЦЕННОСТИ (your_migration_file, 1)

  • Переименуйте файл миграции: mv your_migration_file your_migration_file.php

  • Раскомментируйте свою сеялку в DatabaseSeeder.php

И все готово. Теперь, когда вы запустите php artisan migrate, любая миграция должна быть выполнена (кроме новой, если вы добавите новые файлы миграции).

Ответ 5

Из документов Laravel

По умолчанию команда db: seed запускает класс DatabaseSeeder, который может использоваться для вызова других семенных классов. Однако вы можете использовать параметр -class, чтобы указать конкретный класс сеялки для индивидуального запуска

php artisan db:seed --class=UserTableSeeder

для миграции вам нужно будет переместить файлы в другую папку (те, которые вы хотите перенести) и указать путь

php artisan migrate --path=database/migrations/temp

Ответ 6

просто комментарий идеи сеялка и схема. это так, я думаю,

//$this->call(HvAccountsSeeder::class);

//Schema::create('users', function (Blueprint $table) {
          //  $table->increments('id');
          //  $table->string('name');
          //  $table->string('email')->unique();
          //  $table->string('password');
          //  $table->rememberToken();
           // $table->timestamps();
       // });
// Schema::drop('users');

Ответ 7

Чтобы ответить на ваш вопрос, у Laravel нет способа сделать это в настоящее время.

Если вы правильно поняли, я предполагаю, что вы ищете способ временно отключить/пропустить определенный класс из базы данных DatabaseSeeder по умолчанию.

Вы можете легко создать свою собственную команду, которая примет строку, такую ​​как имя модели/таблицы, и попытается выполнить миграцию и семя для этой конкретной таблицы. Вам просто нужно что-то вроде следующего:

public function handle(){ //fire for Laravel 4.*

    $tables = explode(',', $this->option('tables'));//default []
    $skip = explode(',', $this->option('skip'));//default [] 
    $migrations = glob("*table*.php");//get all migrations
    foreach($migrations as $migrate){
        //if tables argument is set, check to see if part of tables
        //if file name not like any in skip.. you get the point