如何禁用Laravel原生migrate命令但保留模块migrate功能?
禁用Laravel原生migrate命令同时保留模块迁移功能的解决办法
我在使用nWidart/laravel-modules开发多模块Laravel项目,每个模块都配置了独立的数据库连接和对应的迁移文件。为了只执行模块迁移、跳过Laravel原生的迁移文件,我写了app:migrate-modules命令来循环执行各个模块的迁移;同时因为项目没有默认数据库连接,我覆盖了原生的migrate命令,提示用户使用自定义的迁移命令。但这么做之后,模块的迁移功能失效了——原因是laravel-modules的迁移命令内部会调用原生的migrate命令,而我覆盖后的命令只是给出提示,没有执行实际的迁移逻辑。
以下是几种可行的解决办法:
方案1:移除原生migrate命令而非覆盖
不要直接注册同名的migrate命令,而是先移除原生命令,再注册提示用的自定义命令。这样laravel-modules的迁移命令因为直接调用底层Migrator类执行逻辑,不会受到影响。
在AppServiceProvider的boot方法中添加代码:
public function boot() { // 移除Laravel原生的migrate命令 \Illuminate\Support\Facades\Artisan::forgetCommand('migrate'); // 注册自定义提示命令 \Illuminate\Support\Facades\Artisan::command('migrate', function () { $this->comment('Command NOT AVAILABLE. Use this: php artisan app:migrate-modules'); })->describe('原生迁移命令已禁用,请使用app:migrate-modules执行模块迁移'); }
方案2:拦截原生migrate命令的执行(灵活控制)
如果需要保留原生migrate命令的内部功能供模块调用,同时禁止用户直接执行,可以修改原生命令的执行逻辑,判断调用来源:
在AppServiceProvider的boot方法中添加代码:
use Illuminate\Database\Console\Migrations\MigrateCommand; public function boot() { $this->app->extend(MigrateCommand::class, function ($command, $app) { // 保存原生的handle方法 $originalHandle = $command->handle; // 重写handle方法 $command->handle = function () use ($command, $originalHandle) { // 判断是否是模块迁移触发的调用 $argv = collect(request()->server('argv') ?? []); $isModuleMigration = $argv->contains('module:migrate') || $argv->filter(fn($arg) => str_starts_with($arg, '--module='))->isNotEmpty(); if (!$isModuleMigration) { $this->comment('Command NOT AVAILABLE. Use this: php artisan app:migrate-modules'); return; } // 执行原生的迁移逻辑 $originalHandle->call($command); }; return $command; }); }
这个方案会让原生migrate命令只有在模块迁移触发时才正常执行,用户直接调用时则提示禁用。
方案3:直接调用模块迁移命令类(绕开Artisan命令调用)
修改你的app:migrate-modules命令,直接实例化模块迁移命令类执行,而非通过Artisan::call调用命令,完全绕开Artisan命令的解析流程:
use Nwidart\Modules\Commands\MigrateCommand as ModuleMigrateCommand; use Nwidart\Modules\Facades\Module; use Symfony\Component\Console\Input\ArrayInput; // 在app:migrate-modules命令的handle方法中 public function handle() { foreach (Module::all() as $module) { $databaseConnection = config($module->getLowerName() . '.database_connection'); if (!empty($databaseConnection)) { // 实例化模块迁移命令 $migrateCommand = $this->app->make(ModuleMigrateCommand::class); $migrateCommand->setLaravel($this->laravel); // 设置命令参数并执行 $input = new ArrayInput([ 'module' => $module->getName(), '--database' => $databaseConnection, '--force' => true ]); $migrateCommand->run($input, $this->output); } } }
内容的提问来源于stack exchange,提问作者Giacomo M
相关产品推荐
相关产品推荐

