ThinkPHP 8.0 已彻底移除内置迁移功能,需手动安装 think-phinx、配置 phinx.php、严格遵循 database/migrations 路径与 Database\Migrations 命名空间,并仅使用 change() 方法执行迁移。

ThinkPHP 8.0 已完全移除内置迁移功能,php think migrate:* 系列命令在 TP8 中默认不可用——这不是配置问题,而是架构级删除。
TP8 迁移命令不存在?先确认是否还在用旧扩展
TP8 不再兼容 topthink/think-migration,该包在 TP8 下会报 Class not found 或静默失败。官方转向标准 Phinx 集成,但需手动安装并初始化配置文件。
- 必须执行
composer require topthink/think-phinx(不是think-migration) - 运行
php think phinx:init生成phinx.php,它会读取config/database.php自动适配连接 - 检查
phinx.php中的paths.migrations是否指向database/migrations(TP8 要求路径严格在此) - 若仍提示
Command "phinx:migrate" is not defined,说明think-phinx的命令类未被自动注册,需手动在config/console.php中添加:\think\phing\Command::class
迁移文件命名与命名空间必须符合 TP8 PSR-4 规范
TP8 的自动加载器只认 database/migrations/ 下、命名空间为 Database\Migrations\* 的类。任何偏差都会导致 phinx:migrate 找不到文件或报错。
- 文件路径只能是
database/migrations/20240101000000_create_users_table.php,不能是app/database/migrations/或application/migration/ - 类声明必须以
namespace Database\Migrations;开头,且类名须与文件名一致(如class CreateUsersTable) - 不支持下划线以外的分隔符:
20240101000000_create_users_table.php✅,20240101000000-create-users-table.php❌ - 若用了自定义基类(如
AppMigration),它也必须放在可自动加载路径下,并声明为namespace Database\Migrations;或正确 PSR-4 映射
up()/down() 失效?TP8 只支持 change() 方法
TP8 的 think-phinx 集成默认禁用 up()/down(),只识别 change()。写错方法名会导致迁移静默跳过,表结构毫无变化。
立即学习“PHP免费学习笔记(深入)”;
- 迁移类中必须定义
public function change(): void,不能只写up() -
change()内部用$this->table('users')->create()即可,Phinx 会自动推导回滚逻辑(删表) - 若需手动控制正逆操作(比如加字段后又删字段),仍可用
up()/down(),但必须在phinx.php中显式开启:'default_migration_table' => 'migrations'并确保命令加--no-transaction避免事务冲突 - 避免在
change()中调用模型或依赖容器服务——迁移阶段app()可能未完全启动,只应使用$this->table()或原生Db::execute()
执行迁移后表没创建?重点查三个地方
最常见的“没反应”不是命令失败,而是 Phinx 认为当前迁移已执行过,或环境配置错位。
- 先看
phinxlog表(不是migration)是否存在,且是否有记录;若无,说明phinx:init没成功或数据库连接指向了空库 - 运行
php think phinx:status,状态为up表示已执行,down才是待执行;若全为up却没建表,大概率是phinx.php的environments配置和当前 ThinkPHP 环境(APP_ENV)不匹配 - Linux 下注意文件权限:
database/migrations/目录需对 Web 用户(如www-data)可读,否则 CLI 能跑、Webhook 触发时会卡住 - 时间戳重复导致顺序错乱?Phinx 按文件名排序,同时间戳下按字母序(
a在b前),但 Git 合并时容易丢序——建议团队统一用php think phinx:create生成,别手改时间戳
TP8 的迁移本质是 Phinx 的封装层,它不处理环境差异、不校验表存在性、也不保证事务安全。所有「为什么没执行」的问题,最终都落在 phinx.php 配置、文件路径/命名空间、以及 change() 方法的写法上——这三个点漏掉任何一个,迁移就只是个空转的命令。



















