如何运行 Laravel 迁移和 DB 播种机,除了一个
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35191709/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to run laravel migration and DB seeder except one
提问by Niklesh Raut
I am having many migration and seeder files to run, Although I will need to run all files but currently I need to skip one migration and seeder.
我有许多迁移和播种器文件要运行,虽然我需要运行所有文件,但目前我需要跳过一个迁移和播种器。
How could I skip one file from laravel migration and db seeder command.
我怎么能从 laravel 迁移和 db seeder 命令中跳过一个文件。
I do not want to delete files from the migrations or seeds folder to skip the file.
我不想从迁移或种子文件夹中删除文件以跳过该文件。
采纳答案by LombaX
Laravel doesn't give you a default method to do it. However, you can create your own console commands and seeder to achieve it.
Let's say you have this default DatabaseSeeder
class:
Laravel 没有给你一个默认的方法来做到这一点。但是,您可以创建自己的控制台命令和播种器来实现它。
假设您有这个默认DatabaseSeeder
类:
class DatabaseSeeder extends Seeder
{
public function run()
{
$this->call(ExampleTableSeeder::class);
$this->call(UserSamplesTableSeeder::class);
}
}
the goal is to create a new command overriding "db:seed" and pass a new parameter, an "except" parameter, to the DatabaseSeeder
class.
目标是创建一个覆盖“db:seed”的新命令,并将一个新参数“except”参数传递给DatabaseSeeder
类。
This is the final code, I created on my Laravel 5.2 instance and tried:
这是最终代码,我在 Laravel 5.2 实例上创建并尝试:
Command, put in app/Console/Commands, don't forget to update your Kernel.php:
命令,放入app/Console/Commands,不要忘记更新你的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);
}
}
It the code, you'll find that I commented the line that calls the seed and added an echo for testing purposes.
在代码中,您会发现我注释了调用种子的行并添加了一个回声用于测试目的。
Executing this command:
执行这个命令:
php artisan db:seed-except
php artisan db:seed-except
will give you:
会给你:
calling ExampleTableSeeder
calling UserSamplesTableSeeder
调用 ExampleTableSeeder
调用 UserSamplesTableSeeder
However, adding "except":
但是,添加“除外”:
php artisan db:seed-except --except=ExampleTableSeeder
php artisan db:seed-except --except=ExampleTableSeeder
will give you
会给你
calling UserSamplesTableSeeder
调用 UserSamplesTableSeeder
This works overriding the default call
method of your DatabaseSeeder
class and calling the parent only if the name of the class is not in the $except variable. The variable is populated by the SeedExcept
custom command.
这可以覆盖类的默认call
方法,DatabaseSeeder
并且仅当类的名称不在 $except 变量中时才调用父类。该变量由SeedExcept
自定义命令填充。
Regarding migrations, the thing is similar but a little bit more difficult.
关于迁移,事情是相似的,但有点困难。
I can't give you tested code for this by now, but the thing is:
我现在不能给你测试过的代码,但问题是:
- you create a
migrate-except
command that overrides theMigrateCommand
class (namespace Illuminate\Database\Console\Migrations, located in vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/MigrateCommand.php). - the
MigrateCommand
takes aMigrator
object (namespace Illuminate\Database\Migrations, path vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php) in the constructor (injected via IoC). TheMigrator
class owns the logic that reads all the migrations inside the folder and execute it. This logic is inside therun()
method - create a subclass of
Migrator
, for exampleMyMigrator
, and override therun()
method to skip the files passed with the special option - override the
__construct()
method of yourMigrateExceptCommand
and pass yourMyMigrator
:public function __construct(MyMigrator $migrator)
- 您创建一个
migrate-except
覆盖MigrateCommand
类的命令(命名空间 Illuminate\Database\Console\Migrations,位于 vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/MigrateCommand.php)。 - 在构造函数中
MigrateCommand
接受一个Migrator
对象(命名空间 Illuminate\Database\Migrations,路径 vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php)(通过 IoC 注入)。本Migrator
类拥有读取所有的文件夹内的迁移和执行它的逻辑。这个逻辑在run()
方法里面 Migrator
例如MyMigrator
,创建 的子类并覆盖run()
方法以跳过使用特殊选项传递的文件- 覆盖
__construct()
您的方法MigrateExceptCommand
并传递您的MyMigrator
:public function __construct(MyMigrator $migrator)
If I have time I'll add the code for an example before the bounty ends
如果我有时间,我会在赏金结束前添加示例代码
EDITas promised, here's an example for migrations:
按照承诺进行编辑,这是一个迁移示例:
MyMigrator class, extends Migrator and contains the logic to skip files:
MyMigrator 类,扩展 Migrator 并包含跳过文件的逻辑:
namespace App\Helpers;
use Illuminate\Database\Migrations\Migrator;
class MyMigrator extends Migrator
{
public $except = null;
// run() method copied from it's 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
}
}
The MigrateExcept custom command
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'],
];
}
}
Last, you need to add this to a service provider to permit the Laravel IoC resolve the dependencies
最后,您需要将其添加到服务提供者以允许 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']);
});
}
}
Don't forget to add Commands\MigrateExcept::class
in the Kernel.php
不要忘记Commands\MigrateExcept::class
在 Kernel.php 中添加
Now, if you execute
现在,如果你执行
php artisan migrate-except
php artisan migrate-except
you have:
你有:
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"
...
but adding the except param:
但是添加了except参数:
php artisan migrate-except --except=2014_04_24_110151_create_oauth_scopes_table
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"
So, recap:
所以,回顾一下:
- we create a custom migrate-except command,
MigrateExcept
class, extending MigrateCommand - we create a custom migrator class,
MyMigrator
, extending the behavior of the standardMigrator
- when MigrateExcept is fire(), pass the name of the file to skip to our
MyMigrator
class MyMigrator
overrides therun()
method ofMigrator
and skip the passed migration- More: since we need to instruct Laravel IoC about the new created classes, so it can inject them correctly, we create a Service Provider
- 我们创建一个自定义的 migrate-except 命令,
MigrateExcept
类,扩展 MigrateCommand - 我们创建了一个自定义迁移器类
MyMigrator
,扩展了标准的行为Migrator
- 当 MigrateExcept 为 fire() 时,传递文件名跳转到我们的
MyMigrator
类 MyMigrator
覆盖run()
方法Migrator
并跳过通过的迁移- 更多:由于我们需要向 Laravel IoC 指示新创建的类,以便它可以正确注入它们,我们创建了一个服务提供者
The code is tested so it should work correctly on Laravel 5.2 (hoping that cut&paste worked correctly :-) ...if anyone has any doubt leave a comment
该代码已经过测试,因此它应该可以在 Laravel 5.2 上正常工作(希望剪切和粘贴工作正常:-) ...如果有人有任何疑问,请发表评论
回答by Dastur
Skipping seeds are very simple, migrations not so much. To skip a seed, remove the following from your DatabaseSeeder class.
跳过种子非常简单,迁移不是那么多。要跳过种子,请从 DatabaseSeeder 类中删除以下内容。
$this->call(TableYouDontWantToSeed::class);
For migrations, There are three ways you can do it:
对于迁移,您可以通过三种方式进行:
- Put the class you don't want to migrate into a different folder.
- Insert your migrations into the database manually (Bindesh Pandya's answer elaborated).
- Rename the file that you don't want to migrate to something like
UsersTableMigration.dud
.
- 将您不想迁移的课程放到不同的文件夹中。
- 手动将您的迁移插入数据库(详细说明了 Bindesh Pandya 的回答)。
- 将您不想迁移的文件重命名为
UsersTableMigration.dud
.
Hope this helps
希望这可以帮助
回答by Bindesh Pandya
I also faced the same problem in my project but after long time wasting in R & D i have found that Laravel does not provide any way to do this with migration and seeding but you have 2 ways to do this.
我在我的项目中也遇到了同样的问题,但是在研发上浪费了很长时间后,我发现 Laravel 没有提供任何方法来通过迁移和播种来做到这一点,但你有两种方法可以做到这一点。
1) you'll save a lot of time just putting them into different folders. You could theoretically make your own artisan commandthat does what you want, or spoofs its by making directories, moving files, and running php artisan migrate.
1) 只需将它们放入不同的文件夹中,您就可以节省大量时间。理论上,您可以创建自己的 artisan 命令来执行您想要的操作,或者通过创建目录、移动文件和运行 php artisan migrate 来欺骗它。
For the seeders, just make a seeder and call the others seeders you want to run from with in it. Then just be explicit about what seeder you want to run. Try php artisan db:seed --help
for more details there.
对于播种机,只需制作播种机并调用其他要运行的播种机即可。然后明确说明您要运行的播种机。db:seed --help
在那里尝试 php artisan以获取更多详细信息。
2) you can create a table Manually (which has same name as migration table is creating in you db) and insert the values of migration like this
2)您可以手动创建一个表(与在您的数据库中创建的迁移表具有相同的名称)并像这样插入迁移的值
insert into migrations(migration, batch) values('2015_12_08_134409_create_tables_script',1);
so migrate command will not create table which is already exist in migration table.
所以 migrate 命令不会创建迁移表中已经存在的表。
回答by Kamil Kie?czewski
If you want just omit (but keep) migration and seeder:
如果您只想省略(但保留)迁移和播种机:
- Rename your migration by removing
.php
extension:mv your_migration_file.php your_migration_file
- Go to:
DatabaseSeeder.php
and comment out line with your unwanted seeder://$this->call('YourSeeder');
. - Run:
php artisan migrate --seed
Execute below sql query on db (be careful, there should be migration file name WITHOUT extension) (this will prevent artisan migrate to execute your_migration_file in future):
INSERT INTO
migrations
(migration
,batch
) VALUES (your_migration_file
, 1)Rename back your migration file:
mv your_migration_file your_migration_file.php
- Uncomment your seeder in
DatabaseSeeder.php
- 通过删除
.php
扩展重命名您的迁移:mv your_migration_file.php your_migration_file
- 转到:
DatabaseSeeder.php
并注释掉您不需要的播种机的行://$this->call('YourSeeder');
。 - 跑:
php artisan migrate --seed
在 db 上执行下面的 sql 查询(注意,应该有没有扩展名的迁移文件名)(这将阻止 artisan migrate 将来执行 your_migration_file):
插入
migrations
(migration
,batch
) 值 (your_migration_file
, 1)重命名您的迁移文件:
mv your_migration_file your_migration_file.php
- 取消注释您的播种机
DatabaseSeeder.php
And you are done. Now when you run php artisan migrate
any migration should be executed (except new one if you add some new migration files).
你已经完成了。现在,当您运行时,php artisan migrate
应该执行任何迁移(如果添加一些新的迁移文件,则新迁移除外)。
回答by Hamelraj
just an idea comment seederand schema. this is the way i guess
只是一个想法评论播种机和架构。这是我猜的方式
//$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');
回答by Chibueze Opata
To directly answer your question, Laravel does not have a way to do this currently.
为了直接回答你的问题,Laravel 目前没有办法做到这一点。
If I understand you correctly, I assume you're looking for a way to temporarily disable/skip a specific class from the default DatabaseSeeder.
如果我理解正确,我假设您正在寻找一种方法来临时禁用/跳过默认 DatabaseSeeder 中的特定类。
You can easily create your own commandwhich will accept a string such as a model/table name and attempt to run the migration and seed for that particular table. You will simply need something like the following:
您可以轻松创建自己的命令,该命令将接受诸如模型/表名称之类的字符串,并尝试为该特定表运行迁移和种子。您只需要如下内容:
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