ThinkPHP8 数据库迁移与数据填充完全指南(官方文档补充版)
一、安装与配置
1. 安装迁移扩展
composer require topthink/think-migration
2. 配置文件说明
- 配置文件位于
config/database.php
- 默认迁移表名:
think_migration
- 支持多数据库连接
3. 环境要求
- PHP >= 8.1
- ThinkPHP >= 8.0
- 建议使用 InnoDB 引擎(支持事务)
二、迁移文件操作
1. 创建迁移文件
# 创建基础迁移文件
php think migrate:create CreateUsersTable
# 创建带表名的迁移文件(自动生成基础结构)
php think migrate:create AddEmailToUsersTable --table=users
# 指定数据库连接
php think migrate:create CreateLogsTable --connection=log
2. 迁移文件结构
生成的迁移文件位于 database/migrations
,示例:
<?php
use think\migration\Migrator;
use think\migration\db\Column;
class CreateUsersTable extends Migrator
{
/**
* 执行迁移(向上操作)
*/
public function up()
{
$table = $this->table('users');
$table->addColumn('name', 'string', ['limit' => 50])
->addColumn('email', 'string', ['limit' => 100, 'unique' => true])
->addColumn('password', 'string', ['limit' => 100])
->addTimestamps() // 自动添加 create_time 和 update_time 字段
->create();
}
/**
* 回滚迁移(向下操作)
*/
public function down()
{
$this->dropTable('users');
}
}
三、常用字段类型
字段类型 | 描述 | 示例用法 |
---|---|---|
integer | 整数类型 | ->addColumn('age', 'integer') |
biginteger | 大整数类型 | ->addColumn('user_id', 'biginteger') |
string | 字符串类型 | ->addColumn('name', 'string', ['limit' => 50]) |
text | 长文本类型 | ->addColumn('content', 'text') |
datetime | 日期时间类型 | ->addColumn('created_at', 'datetime') |
timestamp | 时间戳类型 | ->addColumn('updated_at', 'timestamp') |
boolean | 布尔类型 | ->addColumn('status', 'boolean', ['default' => 0]) |
decimal | 高精度小数 | ->addColumn('price', 'decimal', ['precision' => 10, 'scale' => 2]) |
enum | 枚举类型 | ->addColumn('gender', 'enum', ['values' => ['male', 'female', 'other']]) |
四、表结构操作
1. 创建表
public function up()
{
$table = $this->table('users', [
'engine' => 'InnoDB',
'charset' => 'utf8mb4',
'comment' => '用户表',
'collation' => 'utf8mb4_unicode_ci'
]);
$table->addColumn('id', 'integer', ['identity' => true]) // 自增ID(默认主键)
->addColumn('username', 'string', ['limit' => 30])
->addColumn('email', 'string', ['limit' => 100, 'unique' => true])
->addColumn('password', 'string', ['limit' => 100])
->addColumn('status', 'boolean', ['default' => 1])
->addIndex(['username']) // 普通索引
->addUniqueIndex(['email']) // 唯一索引
->addTimestamps() // 自动添加 create_time 和 update_time
->addSoftDelete() // 添加 delete_time 软删除字段
->create();
}
2. 修改表
添加字段:
public function up()
{
$this->table('users')
->addColumn('phone', 'string', ['limit' => 20, 'after' => 'email'])
->update();
}
修改字段:
public function up()
{
$this->table('users')
->changeColumn('phone', 'string', ['limit' => 11, 'default' => ''])
->update();
}
删除字段:
public function up()
{
$this->table('users')
->removeColumn('phone')
->update();
}
3. 添加外键约束
public function up()
{
$this->table('posts')
->addColumn('user_id', 'integer')
->addColumn('title', 'string')
->addColumn('content', 'text')
->addForeignKey('user_id', 'users', 'id', ['delete' => 'CASCADE', 'update' => 'CASCADE'])
->update();
}
五、执行迁移命令
1. 执行所有未迁移的文件
php think migrate:run
2. 回滚上一次迁移
php think migrate:rollback
3. 回滚到指定版本
php think migrate:rollback --target=20250726101500 # 指定时间戳
4. 重置所有迁移(先回滚再执行)
php think migrate:reset
5. 刷新数据库(重置并重新执行所有迁移)
php think migrate:refresh
6. 查看迁移状态
php think migrate:status
7. 指定数据库连接
php think migrate:run --connection=db_log # 指定日志数据库
六、数据填充操作
1. 创建数据填充文件
php think seed:create Users # 创建Users表的数据填充器
2. 编写数据填充逻辑
<?php
use think\migration\Seeder;
use think\facade\Db;
class Users extends Seeder
{
/**
* 填充数据
*/
public function run()
{
$data = [];
for ($i = 1; $i <= 10; $i++) {
$data[] = [
'username' => 'user' . $i,
'email' => 'user' . $i . '@example.com',
'password' => password_hash('123456', PASSWORD_DEFAULT),
'create_time' => date('Y-m-d H:i:s'),
'update_time' => date('Y-m-d H:i:s')
];
}
// 使用批量插入提高性能
Db::name('users')->insertAll($data);
}
}
3. 执行数据填充
php think seed:run # 执行所有填充器
php think seed:run --seeder Users # 执行指定填充器
七、高级技巧
1. 使用 change() 方法(简化双向操作)
public function change()
{
$table = $this->table('users');
if (!$table->exists()) {
// 创建表
$table->addColumn('username', 'string')
->addColumn('email', 'string')
->create();
} else {
// 修改表
$table->addColumn('phone', 'string')
->update();
}
}
2. 使用事务
public function up()
{
$this->getAdapter()->beginTransaction();
try {
$this->table('table1')->addColumn(...)->create();
$this->table('table2')->addColumn(...)->create();
$this->getAdapter()->commit();
} catch (\Exception $e) {
$this->getAdapter()->rollBack();
throw $e;
}
}
3. 创建数据库快照
php think migrate:snapshot # 创建当前数据库结构快照
4. 指定迁移文件路径
php think migrate:run --path=database/migrations/custom # 指定自定义路径
八、最佳实践
1. 命名规范
- 迁移文件:
YYYYMMDDHHMMSS_表名_操作.php
(自动生成) - 表名:使用小写字母和下划线(如
user_info
) - 字段名:使用小写字母和下划线(如
create_time
)
2. 避免复杂SQL
- 单个迁移文件只做单一变更
- 避免在迁移中执行数据迁移操作
3. 测试迁移
- 在开发环境充分测试
- 使用测试数据库验证回滚功能
4. 生产环境注意事项
- 迁移前备份数据库
- 使用
--pretend
参数预览变更 - 避免在高峰期执行大型迁移
5. 团队协作
- 迁移文件提交到版本控制系统
- 避免多人同时修改同一迁移文件
- 拉取代码后先执行
php think migrate:run
九、常见问题与解决方案
1. 迁移文件冲突
- 问题:多个迁移文件时间戳相近导致执行顺序异常
解决方案:使用
--timestamp
参数手动指定时间戳php think migrate:create NewTable --timestamp=20250726153000
2. 外键约束错误
- 问题:删除表时外键约束阻止操作
解决方案:在
down()
方法中先删除外键public function down() { $this->table('posts') ->dropForeignKey('user_id') ->update(); $this->dropTable('posts'); }
3. 数据填充重复问题
- 问题:多次执行填充器导致数据重复
解决方案:在填充前清空表
public function run() { Db::name('users')->delete(true); // 清空表 // 填充新数据 }
4. 迁移性能问题
- 问题:大型表迁移缓慢
解决方案:
- 分批次执行数据迁移
- 使用数据库原生工具导入大型数据
- 避免在迁移中使用复杂查询
评论 (0)