
codeigniter 4 原生不支持直接运行单个迁移文件,但可通过自定义 cli 命令调用 `migrationrunner::force()` 方法实现精准控制,适用于模块化项目中按需执行特定迁移(如仅运行 sales 模块的迁移)。
在模块化 CodeIgniter 4 项目中,常需按业务域(如 blog、storage、sales)组织迁移文件,并在部署或调试时仅执行某一个迁移类(而非全部或按时间戳顺序批量执行)。遗憾的是,CI4 官方 spark migrate 命令仅支持指定命名空间、数据库组或回滚到某版本,不提供“运行指定文件”的内置能力。但系统底层的 MigrationRunner 类已暴露 force($file, $namespace, $dbgroup) 方法,这正是我们实现目标的关键。
✅ 解决方案:创建自定义命令 migrate:file
我们通过扩展 CI4 的 CLI 系统,构建一个轻量、安全、可复用的命令,用于精准触发任意迁移文件:
步骤 1:生成命令骨架
在项目根目录运行:
php spark make:command MigrateFile --command migrate:file --group Database --suffix Command
该命令将在 app/Commands/MigrateFileCommand.php 创建基础类。
步骤 2:实现核心逻辑(关键代码精简版)
'Full path to migration file relative to ROOTPATH (e.g. "app/Database/Migrations/2023-01-01-000000_CreateSalesTable.php")'
];
protected $options = [
'--namespace' => 'Migration namespace (default: "App")',
'--dbgroup' => 'Database group (default: "default")',
];
public function run(array $params)
{
if (!isset($params[0])) {
CLI::error('Missing migration file path.');
$this->showHelp();
return;
}
$runner = Services::migrations();
$namespace = CLI::getOption('namespace') ?: 'App';
$dbgroup = CLI::getOption('dbgroup') ?: 'default';
try {
// ✅ 核心:force 执行单个文件(自动解析类名、校验、执行 up())
if (!$runner->force(ROOTPATH . $params[0], $namespace, $dbgroup)) {
CLI::error(lang('Migrations.generalFault'));
return;
}
foreach ($runner->getCliMessages() as $msg) {
CLI::write($msg);
}
CLI::success('Migration completed successfully.');
} catch (\Throwable $e) {
$this->showError($e);
}
}
}? 原理说明:$runner->force() 会加载指定 PHP 文件,提取其中的 Migration 类(要求符合命名规范),验证其 up() 方法存在且未被执行过(基于 migrations 表记录),然后执行并写入迁移日志 —— 完全复用 CI4 原生迁移机制,安全可靠。
步骤 3:使用示例
-
执行默认命名空间下的迁移:
php spark migrate:file "app/Database/Migrations/2023-05-10-120000_AddSalesOrderStatus.php"
-
指定模块命名空间与测试数据库:
php spark migrate:file "Modules/Sales/Database/Migrations/2023-05-10-120000_AddSalesOrderStatus.php" \ --namespace "Modules\Sales" \ --dbgroup "testing"
-
在控制器或服务中动态调用(适合自动化场景):
// 在 Controller 或 Service 中 $output = command('migrate:file "app/Database/Migrations/2023-05-10-120000_AddSalesOrderStatus.php"'); log_message('info', 'Sales migration result: ' . $output);
⚠️ 注意事项与最佳实践
- 路径必须准确:$params[0] 是相对于 ROOTPATH 的路径(非绝对路径),且需包含 .php 后缀;
- 命名空间一致性:确保迁移文件中的类命名空间与 --namespace 参数严格匹配(含反斜杠转义);
- 幂等性保障:force() 会检查 migrations 表,若该迁移已记录为成功,则跳过执行,避免重复操作;
- 错误处理:命令已内置异常捕获与 CLI 友好提示,生产环境建议配合日志记录;
- 模块化扩展:可进一步封装 runAll($moduleKey) 辅助函数,遍历 $files['sales'] 数组逐个调用 migrate:file,实现您原始需求。
通过此方案,你不仅解决了“单文件迁移”问题,更获得了一个可维护、可复用、符合 CI4 设计哲学的模块化迁移管理能力。










