
codeigniter 4 原生不支持直接运行单个迁移文件,但可通过自定义 cli 命令调用 `migrationrunner::force()` 方法实现精准迁移控制,支持指定命名空间、数据库组及动态路径。
在 CodeIgniter 4 的数据库迁移体系中,php spark migrate 默认按时间戳顺序执行所有待迁移文件,而 php spark migrate -f
✅ 实现步骤详解
1. 生成命令骨架
在项目根目录执行:
php spark make:command MigrateFile --command migrate:file --group Database --suffix Command
该命令将在 app/Commands/ 下生成 MigrateFileCommand.php。
2. 编写核心逻辑(关键改造)
将生成的文件替换为以下精简可靠的实现(已适配 CI4.4+,兼容命名空间与多数据库组):
'Full migration file path relative to ROOTPATH (e.g., "app/Database/Migrations/2023-01-01-000000_CreateUsersTable.php")'
];
protected $options = [
'--namespace' => 'Migration namespace (default: "App")',
'--dbgroup' => 'Database group name (default: "default")',
];
public function run(array $params)
{
CLI::write('▶️ Running single migration...', 'yellow');
if (!isset($params[0])) {
CLI::error('Error: Missing migration file path.');
$this->showHelp();
return;
}
$runner = Services::migrations();
$namespace = CLI::getOption('namespace') ?: 'App';
$dbgroup = CLI::getOption('dbgroup') ?: 'default';
$filePath = ROOTPATH . $params[0];
if (!is_file($filePath)) {
CLI::error("File not found: {$filePath}");
return;
}
try {
$result = $runner->force($filePath, $namespace, $dbgroup);
if (!$result) {
CLI::error(lang('Migrations.generalFault'));
return;
}
foreach ($runner->getCliMessages() as $msg) {
CLI::write($msg);
}
CLI::write('✅ Migration completed successfully.', 'green');
} catch (\Throwable $e) {
CLI::error('Exception: ' . $e->getMessage());
}
}
}? 关键说明:$runner->force($filePath, $namespace, $dbgroup) 是核心——它绕过版本检查,强制加载并执行指定 PHP 文件中的迁移类,完全满足“按需触发单文件”的诉求。
3. 使用示例
# 执行 App 命名空间下的迁移文件 php spark migrate:file "app/Database/Migrations/2023-05-10-120000_AddSalesOrderTable.php" # 指定模块命名空间(如 Modules\Sales) php spark migrate:file "Modules/Sales/Database/Migrations/2023-06-01-090000_UpdateInvoiceStatus.php" --namespace "Modules\Sales" # 切换至测试数据库组 php spark migrate:file "app/Database/Migrations/2023-01-01-000000_TestDataSeeder.php" --dbgroup "tests"
4. 进阶:在代码中调用(如 Controller 或 Service)
// 在控制器中动态触发迁移
public function triggerSalesMigration()
{
$output = command('migrate:file "app/Database/Migrations/2023-05-10-120000_AddSalesOrderTable.php"');
log_message('info', 'Sales migration output: ' . $output);
return $this->response->setJSON(['status' => 'done', 'output' => $output]);
}⚠️ 注意事项与最佳实践
- 路径必须准确:$params[0] 是相对于 ROOTPATH 的路径,不要包含 ROOTPATH 前缀(命令内部已自动拼接)。
- 命名空间需匹配:确保迁移文件顶部 namespace 声明与 --namespace 参数一致,否则类无法被正确反射加载。
- 幂等性保障:force() 不检查是否已执行,重复运行可能引发 SQL 错误(如重复建表)。建议在业务逻辑中自行校验 migration_version 表或添加 if (! $this->db->tableExists(...)) 防御。
- 生产环境慎用:单文件迁移适合开发/部署调试,正式环境推荐使用标准 migrate 流程保证版本一致性。
- 错误处理:示例中已包含基础异常捕获,实际项目中可扩展日志记录(如写入 writable/logs/)便于追踪。
通过该方案,你不仅能解决模块化迁移的精准调度问题,更可将其封装为团队标准工具——让 php spark migrate:file 成为 CI4 项目中与 migrate 并行的可靠迁移双引擎。










