Search by

haoa / migration

quhao

Lightweight versioned database migrations for Haoa projects

Package info

github.com/hao-php/migration

pkg:composer/haoa/migration

Statistics

Installs: 4

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.1 2026-10-15 06:16 UTC

This package is not auto-updated.

Last update: 2026-10-15 06:18:54 UTC


README

基于 haoa/cli 和 haoa/mix-database 的轻量数据库迁移库,支持 MySQL 和 PostgreSQL。

安装

composer require haoa/migration

项目配置

绑定项目数据库实例和迁移目录:

use App\Container\DB\DB;
use Haoa\Migration\Migration;

Migration::setDatabaseResolver(function () {
    return DB::instance();
});
Migration::setMigrationPath(BASE_PATH . '/database/migrations');

手动注册命令:

use Haoa\Migration\MigrationCommandProvider;

$cmds = array_merge($cmds, MigrationCommandProvider::commands());
Cli::addArrCommand(...$cmds)->run();

使用

php bin/cli.php migrate:make create_users_table
php bin/cli.php migrate:run

迁移文件返回一个带公开 up() 方法的对象。默认不自动开启事务,up() 成功后登记版本;可通过 withinTransaction 为单个迁移开启事务。发生异常时停止后续迁移。

<?php

declare(strict_types=1);

use App\Container\DB\DB;

return new class
{
    public function up(): void
    {
        DB::instance()->raw('CREATE TABLE users (id BIGINT PRIMARY KEY)', []);
    }
};

事务开关

自动事务默认关闭,不区分数据库类型。迁移文件可以通过公开的布尔属性 withinTransaction 控制;未声明该属性时视为 false。

需要将迁移内容与版本登记放入同一个事务时,在对应迁移对象中显式开启:

return new class
{
    /** @var bool 开启此迁移的自动事务。 */
    public $withinTransaction = true;

    /** 执行迁移 */
    public function up(): void
    {
        // 在此编写迁移代码,事务由迁移库统一管理。
    }
};

自动事务开启时,执行顺序为:开始事务 → up() → 登记版本 → 提交。事务只覆盖当前文件,不会将全部待执行文件放入同一个事务。up() 中的数据库操作必须使用配置的同一个数据库实例;不要自行提交或回滚迁移库管理的事务。

开关只控制迁移库是否调用事务接口,不改变数据库本身的能力。MySQL 等数据库的部分 DDL 会隐式提交,开启开关也不能保证整个迁移原子回滚;此类迁移可关闭自动事务。其他连接、文件操作和外部请求也不在此事务的回滚范围内。

关闭自动事务时,up() 成功后仍会登记版本;如果内容已提交但登记失败,应先核对数据库状态,再处理执行记录,避免直接重跑。

已执行迁移的判断流程

运行 migrate:run 时,按以下流程判断和执行迁移:

  1. 扫描迁移目录中的文件,按文件名中的版本号排序。
  2. 获取迁移锁,确保迁移任务不会并发执行;如果 schema_migrations 表不存在,则自动创建。
  3. 一次查询 schema_migrations 中所有已执行的版本号,并保存在内存中。
  4. 逐个检查迁移文件的版本号:已经登记的跳过;未登记的根据 withinTransaction 开关开启事务,再执行其 up() 方法。
  5. 每个迁移执行成功后,将版本号、迁移名称和执行时间写入 schema_migrations,若已开启自动事务则提交;执行或登记失败时尝试回滚已开启的自动事务。
  6. 任务结束时释放迁移锁;发生异常时也会尝试释放锁。

是否执行过的判断在内存中完成,不会为每个迁移文件单独查询数据库,也不是只判断最大的版本号。后来补入的较小版本号,只要尚未登记,也会被执行。

执行记录的保留

schema_migrations 每个迁移文件只保存一条记录,通常无需定期清理。迁移文件和对应的执行记录应长期保留,用于防止重复执行。

删除执行记录后,如果对应的迁移文件仍在目录中,下次运行会再次执行该文件,可能导致重复建表或重复插入数据。