数据库迁移
迁移是以结构化和组织良好的方式修改数据库的便捷途径。虽然可以手动编辑 SQL 片段,但这样就必须告知其他开发者运行这些片段,且在下次部署时,还需跟踪哪些更改需要应用到生产服务器。
migrations 数据库表用于记录已运行的迁移,因此只需确保迁移文件到位,并运行 spark migrate 命令即可将数据库更新至最新状态。还可使用 spark migrate --all 来包含所有命名空间下的迁移。
迁移文件名
迁移文件名由时间戳前缀、下划线(_)和描述性名称(类名)组成。
2024-09-08-013653_AddBlogTable.php
每个迁移都以创建时的时间戳(2024-09-08-013653)编号,格式为 YYYY-MM-DD-HHIISS。
描述性名称(AddBlogTable)是 PHP 类名,因此必须命名为有效的类名。
前缀中的年、月、日和时间可以用连字符(-)、下划线(_)分隔,也可以不分隔。例如:
2012-10-31-100538_AlterBlogTrackViews.php
2012_10_31_100539_AlterBlogAddTranslations.php
20121031100537_AddBlog.php
迁移按数字顺序正向或反向运行,具体取决于所选的操作。这有助于防止团队协作时的编号冲突。
创建迁移
这是一个包含博客功能的新站点的首次迁移。所有迁移文件都存放于 app/Database/Migrations/ 目录,文件名类似于 2022-01-31-013057_AddBlog.php。
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AddBlog extends Migration
{
public function up()
{
$this->forge->addField([
'blog_id' => [
'type' => 'INT',
'constraint' => 5,
'unsigned' => true,
'auto_increment' => true,
],
'blog_title' => [
'type' => 'VARCHAR',
'constraint' => '100',
],
'blog_description' => [
'type' => 'TEXT',
'null' => true,
],
]);
$this->forge->addKey('blog_id', true);
$this->forge->createTable('blog');
}
public function down()
{
$this->forge->dropTable('blog');
}
}
可分别通过 $this->db 和 $this->forge 使用数据库连接和数据库 Forge 类。
此外,也可通过命令行调用来生成迁移文件骨架。详见 命令行工具 中的 make:migration。
备注
由于迁移类是 PHP 类,因此每个迁移文件中的类名必须唯一。
外键
当表包含外键时,删除表或列的操作常会导致迁移失败。若要在运行迁移时临时绕过外键检查,请使用数据库连接中的 disableForeignKeyChecks() 和 enableForeignKeyChecks() 方法。
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AddBlog extends Migration
{
public function up()
{
$this->db->disableForeignKeyChecks();
// Migration rules would go here..
$this->db->enableForeignKeyChecks();
}
}
数据库组
迁移仅针对单个数据库组运行。如果在 app/Config/Database.php 中定义了多个组,默认将针对该配置文件中指定的 $defaultGroup 运行。
有时可能需要为不同的数据库组使用不同的架构。例如,一个数据库用于存储常规站点信息,另一个用于存储核心业务数据。
通过在迁移类中设置 $DBGroup 属性,可确保迁移仅针对特定组运行。此名称必须与数据库组名称完全匹配:
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AddBlog extends Migration
{
protected $DBGroup = 'alternate_db_group';
public function up()
{
// ...
}
public function down()
{
// ...
}
}
备注
记录已运行迁移的 migrations 表将始终在默认数据库组中创建。
命名空间
迁移类库可利用 $psr4 属性匹配目录名,自动扫描在 app/Config/Autoload.php 中定义或从外部源(如 Composer)加载的所有命名空间。它将包含在 Database/Migrations 中找到的所有迁移。
每个命名空间都有独立的版本序列,这有助于在不影响其他命名空间的情况下对各个模块(命名空间)进行升级或回滚。
例如,假设在 Autoload 配置文件中定义了以下命名空间:
$psr4 = [
APP_NAMESPACE => APPPATH,
'MyCompany' => ROOTPATH . 'MyCompany',
];
系统将在 APPPATH/Database/Migrations 和 ROOTPATH/MyCompany/Database/Migrations 中查找迁移。这使得在可复用的模块化代码套件中包含迁移变得非常简单。
命令行工具
CodeIgniter 自带了多个可从命令行使用的 命令,以协助处理迁移任务。这些工具为开发者提供了便利,其核心是调用了 MigrationRunner 类中的相关方法。
migrate
使用所有可用的迁移来迁移数据库组:
php spark migrate
可为 migrate 使用以下选项:
-g- 指定数据库组。若指定,则仅运行该组的迁移;若未指定,则运行所有迁移。-n- 选择命名空间,否则默认使用App。--all- 将所有命名空间迁移至最新。
本例将在 test 数据库组中运行 Acme\Blog 命名空间下的所有新迁移:
Unix 环境:
php spark migrate -g test -n Acme\\Blog
Windows 环境:
php spark migrate -g test -n Acme\Blog
使用 --all 选项时,系统将扫描所有命名空间以查找未运行的迁移。这些迁移会被汇总,并按创建日期排序。这有助于最大限度地减少主应用与各模块之间可能存在的冲突。
migrate:rollback
将所有迁移回滚到初始状态(即迁移 0):
php spark migrate:rollback
可为 migrate:rollback 使用以下选项:
-b- 选择批次:使用正整数指定批次。-f- 强制跳过确认提示,此提示仅在生产环境中出现。
migrate:refresh
通过先回滚所有迁移,再重新运行所有迁移来重置数据库状态:
php spark migrate:refresh
可为 migrate:refresh 使用以下选项:
-g- 指定数据库组。若指定,则仅运行该组的迁移;若未指定,则运行所有迁移。-n- 选择命名空间,否则默认使用App。--all- 刷新所有命名空间。-f- 强制跳过确认提示,此提示仅在生产环境中出现。
migrate:status
列出所有迁移及其运行时间;若尚未运行则显示 '--':
php spark migrate:status
...
+----------------------+-------------------+-----------------------+---------+---------------------+-------+
| Namespace | Version | Filename | Group | Migrated On | Batch |
+----------------------+-------------------+-----------------------+---------+---------------------+-------+
| App | 2022-04-06-234508 | CreateCiSessionsTable | default | 2022-04-06 18:45:14 | 2 |
| CodeIgniter\Settings | 2021-07-04-041948 | CreateSettingsTable | default | 2022-04-06 01:23:08 | 1 |
| CodeIgniter\Settings | 2021-11-14-143905 | AddContextColumn | default | 2022-04-06 01:23:08 | 1 |
+----------------------+-------------------+-----------------------+---------+---------------------+-------+
可为 migrate:status 使用以下选项:
-g- 指定数据库组。若指定,则仅检查该组的迁移;若未指定,则检查所有迁移。
make:migration
在 app/Database/Migrations 中创建一个迁移文件骨架。该命令会自动添加当前时间戳。生成的类名是文件名的大驼峰(PascalCase)版本。
php spark make:migration <class> [options]
可为 make:migration 使用以下选项:
--namespace- 设置根命名空间。默认值:APP_NAMESPACE。--suffix- 在类名后追加组件标题。
以下选项用于生成数据库 Session 的迁移文件:
--session- 生成数据库 Session 的迁移文件。--table- 用于数据库 Session 的表名。默认值:ci_sessions。--dbgroup- 用于数据库 Session 的数据库组。默认值:default。
迁移配置
下表列出了 app/Config/Migrations.php 中所有的迁移配置选项。
配置项 |
默认值 |
选项 |
描述 |
|---|---|---|---|
enabled |
true |
true / false |
启用或禁用迁移。 |
table |
migrations |
无 |
存储架构版本号的表名。
此表始终在默认数据库组( |
timestampFormat |
Y-m-d-His_ |
创建迁移时使用的时间戳格式。 |
|
lock |
false |
true / false |
启用分布式锁,以防止多进程环境(如 Kubernetes)中的并发迁移。 |
类参考
- class CodeIgniter\Database\MigrationRunner
- findMigrations()
- 返回:
迁移文件数组
- 返回类型:
array
返回在
path属性中找到的迁移文件名数组。
- latest($group)
- 参数:
$group (
mixed) -- 数据库组名称,若为 null 则使用默认组。
- 返回:
成功返回
true,失败返回false- 返回类型:
bool
定位命名空间(或所有命名空间)的迁移,确定尚未运行的迁移,并按版本顺序运行(各命名空间交替进行)。
- regress($targetBatch, $group)
- 参数:
$targetBatch (
int) -- 要回滚到的目标批次;正整数指定批次,0 表示回滚所有,负数表示相对批次(例如 -3 表示“回滚三个批次”)。$group (
?string) -- 数据库组名称,若为 null 则使用默认组。
- 返回:
成功返回
true,失败或未发现迁移返回false- 返回类型:
bool
按批次将更改回滚到之前的状态。
<?php $migration->regress(5); $migration->regress(-1);
- force($path, $namespace, $group)
- 参数:
$path (
mixed) -- 有效迁移文件的路径。$namespace (
mixed) -- 所提供迁移的命名空间。$group (
mixed) -- 数据库组名称,若为 null 则使用默认组。
- 返回:
成功返回
true,失败返回false- 返回类型:
bool
强制运行单个迁移文件,不论顺序或批次。系统会根据是否已迁移来自动检测是执行
up()还是down()。备注
建议仅在测试时使用此方法,否则可能导致数据一致性问题。
- setNamespace($namespace)
- 参数:
$namespace (
string|null) -- 应用命名空间。null表示所有命名空间。
- 返回:
当前 MigrationRunner 实例
- 返回类型:
设置类库查找迁移文件的命名空间:
<?php $migration->setNamespace($namespace)->latest();
备注
如果设置为
null,则会在所有命名空间中查找迁移文件。
- setGroup($group)
- 参数:
$group (
string) -- 数据库组名称。
- 返回:
当前 MigrationRunner 实例
- 返回类型:
设置类库查找迁移文件的数据库组:
<?php $migration->setGroup($group)->latest();