当我在 Laravel 中生成迁移时,它会自动看起来像这样:
public function up()
{
Schema::create('comments', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
});
}
但是我想要工作更方便,我想让数据库在创建和更新一行时处理,而不是每次都自己做。 我找到了一种方法让这成为可能:
public function up()
{
Schema::create('comments', function (Blueprint $table) {
$table->increments('id');
$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
});
}
但是现在每次我进行迁移时,我都必须手动更改它,我认为这不是很方便。有谁知道我如何更改 Laravel 中自动生成的迁移?
如果你仔细研究源代码,你会发现:
MigrationCreator
用于进行迁移。原则上您可以执行以下操作:
获取内置迁移文件并将其移动到项目中的另一个文件夹中(例如可能是资源/存根)请注意,即使您不修改它们,也应该复制该文件夹中的其他存根。
然后,覆盖默认迁移创建者以使用此文件,这应该可以工作:
class MyMigrationCreator extends MigrationCreator {
protected function stubPath() {
return base_path("resources"); //Or something valid
}
}
然后在您的应用服务提供商中您可以执行以下操作:
$this->app->instance(MigrationCreator::class, resolve(MyMigrationCreator::class));
这将(希望)“欺骗”laravel 使用您的迁移创建器而不是默认的迁移创建器。然而,创建表并不是经常发生的事情来证明所有这些麻烦都是合理的。
更新:它应该扩展迁移创建者。
在 Laravel 5.6 中似乎无法重写 MigrationCreator 类,因为它直接在 MigrationServiceProvider 中使用:
protected function registerCreator() {
$this->app->singleton('migration.creator', function ($app) {
return new MigrationCreator($app['files']);
});
}
但是您可以通过以下方式破解 MigrationServiceProvider:
overrides/Illuminate/Database
vendor/laravel/framework/src/Illuminate/Database/MigrationServiceProvider.php
复制到 overrides/Illuminate/Database
文件夹中(请注意,类命名空间将保持不变)修改
overrides/Illuminate/Database/MigrationServiceProvider.php
:
protected function registerCreator() {
$this->app->singleton('migration.creator', function ($app) {
return new MyMigrationCreator($app['files']);
});
}
修改您的
composer.json
("Illuminate\\"
):
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/",
"Illuminate\\": "overrides/Illuminate"
}
},
运行
composer dump-autoload
。作曲家会说
`Warning: Ambiguous class resolution, "Illuminate\Database\MigrationServiceProvider" was found in both "$baseDir . '/overrides/Illuminate/Database/MigrationServiceProvider.php" and "/vendor/laravel/framework/src/Illuminate\Database\MigrationServiceProvider.php", the first will be used.`
现在你的假
MigrationServiceProvider
将被使用而不是 Laravel 的,但你将无法使用原始的。这就是我们复制整个文件的原因。
实际上,通过这种方式,您可以重写
MigrationCreator
类,但是代码量很大,您实际上需要使用 MyMigrationCreator
类来扩展它,并重写一些方法,例如 stubPath()
以及可能的 create()
。但是 MigrationServiceProvider
可以非常安全地重写,因为它包含几个小方法,这些方法在 Laravel 6 之前不太可能改变
使用 Laravel 10 进行测试。
定制
MigrationCreator
:
<?php
namespace App\Services;
use Illuminate\Database\Migrations\MigrationCreator as Creator;
class MigrationCreator extends Creator
{
// Custom Changes
}
定制
MigrateMakeCommand
:
use Illuminate\Database\Console\Migrations\MigrateMakeCommand as Command;
use App\Services\MigrationCreator; # <- Custom Creator!
use Illuminate\Support\Composer;
class MigrateMakeCommand extends Command
{
/**
* Create a new migration install command instance.
*
* @param \App\Services\MigrationCreator $creator
* @param \Illuminate\Support\Composer $composer
*/
public function __construct(MigrationCreator $creator, Composer $composer)
{
parent::__construct($creator, $composer);
}
// Custom Changes
}
ServiceProvider
:
use Illuminate\Support\ServiceProvider;
use Illuminate\Contracts\Foundation\Application;
use App\Console\Commands\Migrations\MigrateMakeCommand; # <- Custom Command!
use App\Services\MigrationCreator; # <- Custom Creator!
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
$this->registerMigrateMakeCommand();
}
/**
* Register a custom make:migration command.
*
* @return void
*/
protected function registerMigrateMakeCommand(): void
{
$this->app->singleton(MigrateMakeCommand::class, function (Application $app) {
$creator = new MigrationCreator($app['files'], $app->basePath('stubs'));
$composer = $app['composer'];
return new MigrateMakeCommand($creator, $composer);
});
}
}