You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何禁用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 10:43:17