Laravel+Hyn多租户中passport:install重复执行全量迁移问题
问题原因分析
1. Passport 11的passport:install命令行为变更
Passport 11版本开始,passport:install命令默认会自动执行所有未完成的应用迁移,而非仅运行Passport自身的迁移。这和Passport 10及之前的版本逻辑不同——旧版本的install命令仅负责生成加密密钥,不会触发全局迁移。
2. 多租户上下文未正确切换
在创建租户的流程中调用Artisan::call('passport:install')时,没有切换到新创建租户的数据库连接,命令依然使用默认的system数据库连接。此时Passport触发的全局迁移会包含Hyn多租户的系统表迁移(比如websites表),而这些表在system库中早已存在,因此抛出表已存在的错误。
3. Laravel 10的命令上下文调整
Laravel 10对Artisan命令的执行上下文做了优化,但在多租户场景下,可能导致命令无法自动继承当前正在创建的租户连接,反而 fallback 到默认的系统数据库连接,进一步加剧了这个问题。
解决办法
方法1:拆分passport:install的操作,避免全局迁移
直接跳过passport:install的自动迁移逻辑,手动拆分密钥生成和Passport迁移步骤:
// 创建租户后,切换到租户上下文(以Hyn为例) $tenant = Tenant::create($request); $tenant->run(function () { // 仅生成Passport加密密钥 Artisan::call('passport:keys'); // 仅运行Passport自身的迁移 Artisan::call('migrate', [ '--path' => 'vendor/laravel/passport/database/migrations', '--force' => true ]); });
方法2:使用--skip-migration参数阻止迁移
调用passport:install时添加--skip-migration参数,让命令只生成密钥,不触发任何迁移:
$tenant->run(function () { Artisan::call('passport:install', ['--skip-migration' => true]); // 手动执行Passport迁移 Artisan::call('migrate', ['--path' => 'vendor/laravel/passport/database/migrations']); });
方法3:确保命令使用租户数据库连接
如果需要保留passport:install的完整流程,必须明确指定命令使用租户的数据库连接:
$tenant = Tenant::create($request); $connectionName = $tenant->connection_name; // 获取Hyn租户的连接名 Artisan::call('passport:install', [ '--database' => $connectionName, '--force' => true ]);
内容的提问来源于stack exchange,提问作者Divine Teyi
相关产品推荐
相关产品推荐

