我为什么创建 Migrun
I’m sorry, but I can’t retrieve the content from external links. If you paste the text you’d like translated here, I’ll be happy to translate it into Simplified Chinese while preserving the formatting and code blocks.
现有 PHP 迁移工具的问题
我主要使用的 PHP 项目 不 位于像 Laravel 或 Symfony 这样的完整框架内部——这些框架自带基于 ORM 的迁移工具。
虽然已有独立的迁移工具(Phinx、Phpmig、Phoenix),但它们存在一些困扰我多年的问题。
Phinx 并不是真正的独立工具
- 它会拉入 Cake 框架的核心。
- 服务容器集成是一个 hack。
- 在 Phinx 迁移中无法将服务注入。
- 人们只能通过全局静态访问或其他变通方式,把自己的数据库连接或日志器放进迁移。
- 这完全违背了现代 DI(依赖注入)的实践。
- 我希望迁移能够直接声明它们的依赖,并由容器自动解析。
查询构建器增加了不必要的复杂度
迁移系统通常会提供 表构建器——一种基于框架 ORM 的、数据库无关的列、索引和表创建 API。理论上,这可以让你在不重写迁移的情况下切换数据库。但实际上:
- 大多数项目从不切换数据库。我参与的项目也没有。它们会 引入 新的数据库,却不会 替换 旧的。
- 即使真的切换,也必须处理数据库特有的特性、数据类型和行为。
- 构建器 API 无法覆盖所有数据库特定的情况(例如 Laravel 中经典的 “自定义大小的 tiny integer” 问题)。Phinx 更受限制——对于棘手的部分,你仍然需要写原生 SQL。
- 构建器为本来只需要一条
CREATE TABLE语句的操作增加了一层抽象和复杂度。
我并不是说构建器毫无用处,但对许多项目来说,它们是多余的开销。
基于继承的设计
所有工具都采用继承。你的迁移类必须继承 AbstractMigration 基类,这把你锁定在一个类层次结构中。在现代 PHP 中,我们更倾向于组合和接口,而不是继承;基于继承的设计刚性大,且更难与自己的架构集成。
僵硬的命名约定和目录结构
这些工具对使用者强加了命名约定和固定的目录结构。迁移累计到上百个后要归档?这根本不是一个选项——甚至是个麻烦。
代码库陈旧
PHP 生态中的迁移工具没有跟随语言的演进。PHP 现在已经拥有只读类、枚举、命名参数、联合类型、纤程、管道等特性,但迁移工具仍然使用 PHP 5 时代的模式。
I/O 集成是个 hack
Phinx 只能在 Symfony Console 环境下工作,运行器与其高度耦合。想要生成一个列出所有迁移的 HTML 页面?祝你好运。
我想要的
极其简单的需求:
- 为迁移提供一个 interface。实现
up(),可选实现down()。完成。 - 从服务容器 自动注入。声明
PDO $db为参数,即可解析。 - 不需要继承基类。
- 不需要配置文件。
- 不提供捆绑的 CLI。没有 Symfony Console。
- 不使用查询构建器。
- 没有文件命名限制。
- 零运行时依赖——甚至没有实用工具包,亦无 Cake 核心。
- 能够在 任何 数据库、任何技术栈、任何服务容器中工作。
于是我构建了 Migrun。
Source: …
谁适合使用
Migrun 适用于以下开发者:
- 在 Laravel 或 Doctrine 生态系统之外进行 PHP 项目开发。
- 需要一个能够融入现有架构的迁移执行器,而不是强制使用特定架构的工具。
- 更倾向于直接编写 SQL,而不是学习构建器 API。
- 使用服务容器,并希望迁移能够自然地受益于容器。
- 需要轻量且可自行改造的方案,而不是完整的框架。
如果你已经在使用 Laravel 或 Doctrine,它们的迁移系统已经深度集成,建议继续使用它们。Migrun 并不是为取代它们而构建的——它是为其他所有人而生。
How It Works
返回一个 匿名类实例(或闭包)自 PHP 文件。所有参数都会从你的服务容器自动解析。
Simple migration (anonymous class)
// 20260326_181000_a_migration.php
exec(debug('Users table created.');
}
};Reversible migration (implements ReversibleMigration)
// 20260326_181002_reversible_migration.php
exec('CREATE INDEX idx_users_email ON users (email)');
}
public function down(?PDO $db = null): void
{
$db->exec('DROP INDEX idx_users_email');
}
};Closure‑based migration
// 20260326_181008_closure_migration.php
exec(directory(__DIR__ . '/migrations')
->container($container) // any PSR‑11 container for autowiring
->pdoStorage($container->get(PDO::class))
->build();
$migrun->run(); // run pending migrations
$migrun->rollback(1); // roll back the last migration就这么简单——轻量、可组合且不依赖特定框架。
$migrun->status(); // see what's applied and what's pending查看 readme 以获取完整的 CLI 示例(例如 composer migrate:up),或让 AI 工具在一分钟内帮你搭建。
支持 Symfony Console,但并非必须(例如 php bin/console db:migrate)。
架构
Migrun 基于四个简洁的接口构建,这些接口:
- 查找迁移
- 执行迁移
- 解析迁移依赖
- 存储迁移历史
可扩展性
- 纯 SQL 文件? 实现一个新的 executor(单个方法)和一个新的 finder(两个方法)。
- 不同的 DI 容器? 实现一个单一的 invoker 方法。
- 在 Redis 中存储历史? 实现一个新的存储类。
库中没有任何继承、静态方法,也没有全局状态。
试一试吧。它仍处于 beta 阶段——你的反馈可能会影响正式版的发布。
Repository:
Install: composer require dakujem/migrun
(或提示 “从 Packagist 安装 dakujem/migrun,使用推荐的设置并添加通过 Composer 调用的 CLI 脚本。”)