CodeIgniter 4 中如何精准执行单个迁移文件(Migration)
技术百科
霞舞
发布时间:2026-01-19
浏览: 次 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/2025-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/2025-05-10-120000_AddSalesOrderTable.php" # 指定模块命名空间(如 Modules\Sales) php spark migrate:file "Modules/Sales/Database/Migrations/2025-06-01-090000_UpdateInvoiceStatus.php" --namespace "Modules\Sales" # 切换至测试数据库组 php spark migrate:file "app/Database/Migrations/2025-01-01-000000_TestDataSeeder.php" --dbgroup "tests"
4. 进阶:在代码中调用(如 Controller 或 Service)
// 在控制器中动态触发迁移
public function triggerSalesMigration()
{
$output = command('migrate:file "app/Database/Migrations/2025-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 并行的可靠迁移双引擎。
# 将其
# 加载
# 进阶
# 可通过
# 推荐使用
# 将在
# 自定义
# 你不
# app
# 按需
# 不支持
# 工具
# js
# json
# if
# class
# 数据库
# 架构
# this
# 封装
# 命名空间
# php
# sql
# Namespace
# spark
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Win11怎么关闭防火墙通知_屏蔽Win11安全中
- Python装饰器设计思路_功能增强机制说明【指导
- 如何使用Golang包导出规则_控制函数和变量可见
- Win11任务栏怎么调到左边_Win11开始菜单居
- XML的“混合内容”是什么 怎么用DTD或XSD定
- windows如何禁用驱动程序强制签名_windo
- Drupal 中渲染节点时出现 HTML 标签嵌套
- Python函数接口稳定性_版本演进解析【指导】
- MAC的“接续互通”功能无法使用怎么办_MAC检查
- 如何使用Golang捕获并记录协程panic_保证
- Windows10无法连接到Internet_Wi
- Win11怎么清理C盘系统错误报告_Win11清理
- Win11怎么恢复出厂设置_Win11重置此电脑保
- 如何在Golang中定义接口_抽象方法和多态实现
- Win11怎么更改管理员名字 Win11修改账户名
- 如何在 Go 同包不同文件中正确引用结构体
- 如何理解Go指针和内存分配关系_Go Pointe
- php能控制zigbee模块吗_php通过串口与c
- Avalonia如何实现跨窗口通信 Avaloni
- Windows10如何查看蓝屏日志_Win10使用
- Win11怎么关闭开机声音_Win11系统启动提示
- Django密码修改后会话失效的解决方案
- Win10怎样卸载iTunes_Win10卸载iT
- Win11怎么关闭SmartScreen_禁用Wi
- c++的static关键字有什么用 静态变量和静态
- 如何使用Golang encoding/json解
- Win11怎么关闭触摸键盘图标_Windows11
- mac怎么安装adb_MAC配置Android A
- 如何高效获取循环末次生成的 NumPy 数组最后一
- PHP 中如何在函数内持久修改引用变量所指向的目标
- Mac版Final Cut Pro入门_Mac视频
- 如何使用Golang管理跨项目依赖_Golang多
- 如何使用Golang reflect检查方法数量_
- mac怎么安装pip_MAC Python pip
- Windows10系统怎么查看IP地址_Win10
- php485读数据时阻塞怎么办_php485非阻塞
- Windows10电脑怎么设置自动连接WiFi_W
- Win11如何设置系统声音_Win11系统声音调整
- php能跑在stm32上吗_php在stm32微控
- Mac怎么设置鼠标滚动速度_Mac鼠标设置详细参数
- c# 如何用c#实现一个支持优先级的任务队列
- Mac电脑进水了怎么办_MacBook进水后紧急处
- Win11怎么设置快速访问_Windows11文件
- 如何使用Golang table-driven f
- 如何在同包不同文件中正确引用 Go 结构体
- phpstudy本地环境mysql忘记密码_重置m
- 如何在Golang中实现文件下载_Golang文件
- Win11怎么设置任务栏对齐方式_Windows1
- Win11鼠标灵敏度怎么调 Win11鼠标指针移动
- c++中如何使用auto关键字_c++11类型推导


QQ客服