ThinkPHP5数据库迁移工具 migration
什么是Migration?
migration用谷歌翻译是移民的意思,在PHP中我们将它理解为迁移,将Migration用在数据库上就理解为数据库迁移咯。在migration开发之前,我们都是手写sql创建表语句,创建成功之后需要手动在数据库执行,项目初始化光数据库的创建就花费很多时间。
另外在多人团队开发中,如果要求每个开发人员都在本地使用数据库那么我们通常都是将数据库备份成sql文件互相传递,这还并不是很繁琐,繁琐的在于如果数据库某个表的字段出现变动那么就需要将这个变动的sql语句传给每个开发小伙伴让他们在本地都手动的更新下,一次可以这样,但是多次呢?我想在开发团队中这种事情肯定让人头疼咯,所以migration就诞生咯。
Migration就是一些管理数据库结构的文件,这些文件其实都是抽象化的sql,可以通过命令行执行而改变数据库的结构,这些文件都是存放在项目下的,随着项目版本的迭代而迭代。
在开发过程中,如果一位小伙伴改动了数据库的表结构,她只需要生成一个migration文件并推送到版本控制系统中,如:Git,并通知其他小伙伴,其他小伙伴只需要pull然后在命令行执行下migration命令就可以了,简化了传统的数据库变动流程,加快项目的开发。
Migration文件作用
migration 文件的主要作用就是用来管理数据库的结构,其实它是一组sql语句的抽象化,migration 文件可以创建表,删除表,增加字段,删除字段等等基本上所有的数据库操作,其实这就像你自己手动写sql语句一样,只不过在 migration 中你不需要手动的写sql语句,只需要按照它的规则语法调用一下就可以啦。
migrate 命令介绍
ThinkPHP5.1 使用 migration
thinkPHP5 为开发者提供了一整套的 migration 解决方案,不过默认情况下 migration 是没有安装的,需要我们手动安装。将工作目录切换到tp5项目下,执行:
composer require topthink/think-migration v2.0.3
默认安装的TP6版本,这里指定安装tp5.1 的版本为V2.0.3,更多版本地址:https://packagist.org/packages/topthink/think-migration
执行PHP think
命令查看是否安装成功
从图中我们可以看到 migration 和 seed ,表示安装成功了
create 命令
语法格式:PHP think migrate:create TableName
TableName
格式:首字母大写的驼峰法。该命令是用来创建一个 migration 文件,比如这里我们创建一个 Video
的 migration 文件:
PHP think migrate:create Video
第一次执行 Migraton 它会提示一些信息,这里全部统一 yes 就可以啦。创建成功如下:
# PHP think migrate:create Video PHP Warning: Module 'redis' already loaded in UnkNown on line 0 Create migrations directory? [y]/n (yes/no) [yes]: > yes created ./database/migrations/20190804032741_video.PHP
在项目的根目录下多了一个 database 目录,有一个migration文件夹,该文件夹就是用来存放 migration文件,打开可以看到我们刚才创建的 Video 的 migration 文件:
<?PHP use think\migration\Migrator; use think\migration\db\Column; class Video extends Migrator { /** * Change Method. * * Write your reversible migrations using this method. * * More information on writing migrations is available here: * http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class * * The following commands can be used in this method and phinx will * automatically reverse them when rolling back: * * createTable * renaMetable * addColumn * renameColumn * addindex * addForeignKey * * Remember to call "create()" or "update()" and NOT "save()" when working * with the Table class. */ public function change() { } }
Video
表结构如下
字段 | 类型 | 说明 |
---|---|---|
id | int | 主键 |
nickname | varchar(16) | 视频名称 |
varchar(32) | 邮箱 | |
password | varchar64) | 密码 |
删除默认自带的
change
方法,创建up()
方法和down()
方法。up()
方法是在执行run
命令执行的,down()
是在执行rollback
命令执行的。
up()
方法如下 :
public function up() { $table = $this->table('video'); $table->addColumn('name', 'string', ['limit' => 16, 'null' => false,'comment'=>'视频名称']) ->addColumn('email', 'string', ['limit' => 32, 'null' => false,'comment'=>'邮箱']) ->addColumn('password', 'string', ['limit' => 64, 'null' => false,'comment'=>'密码']) ->create(); }
down()
方法如下:
public function down() { $this->dropTable('video'); }
table('video'); $table->addColumn('name', 'string', ['limit' => 16, 'null' => false,'comment'=>'名称']) ->addColumn('email', 'string', ['limit' => 32, 'null' => false,'comment'=>'邮箱']) ->addColumn('password', 'string', ['limit' => 64, 'null' => false,'comment'=>'密码']) ->create(); } // migrate:rollback 时执行 public function down() { $this->dropTable('video'); } }
这样,一个可以创建 video 表的 migration 文件就创建完毕了,接下来,来学习下一个命令。
migrate:run 命令
migration 文件创建完毕,还需要执行 run
命令才可以修改数据库:
PHP think migrate:run
执行成功之后,查看数据库,多了两个表iot_migrations
和iot_video
iot_video
表结构如下
MysqL> desc iot_video; +----------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(16) | NO | | NULL | | | email | varchar(32) | NO | | NULL | | | password | varchar(64) | NO | | NULL | | +----------+-------------+------+-----+---------+----------------+ 4 rows in set (0.07 sec)
之前我定义了 migration 只指定了
nickname
,password
三个字段,但是执行run
命令创建的表中有四个字段,多了一个id
主键?这是thinkPHP5
为我们默认添加的!小伙伴注意啦!如果你的主键字段名为id
就不需要自己手动的指定了。
iot_video
设计表结构查看注释
iot_migrations
表中的内容是什么?
MysqL> select * from iot_migrations G; +----------------+----------------+---------------------+---------------------+------------+ | version | migration_name | start_time | end_time | breakpoint | +----------------+----------------+---------------------+---------------------+------------+ | 20190804032741 | Video | 2019-08-04 11:49:49 | 2019-08-04 11:49:50 | 0 | +----------------+----------------+---------------------+---------------------+------------+ 1 row in set (0.08 sec)
可以看出是刚才执行run命名成功后的一条记录,版本20190804032741是和文件名一一对应的
migrate:status 命令
说明:显示迁移状态
# PHP think migrate:status Status Migration ID Started Finished Migration Name ---------------------------------------------------------------------------------- up 20190804032741 2019-08-04 11:49:49 2019-08-04 11:49:50 Video
列表的形式展示了 migration 的执行情况
migrate:roolback 命令
说明:回滚最后一个或特定的迁移
语法:PHP think migrate:rollback
# PHP think migrate:rollback --help Help: The migrate:rollback command reverts the last migration, or optionally up to a specific version PHP console migrate:rollback PHP console migrate:rollback -t 20111018185412 //指定版本 PHP console migrate:rollback -d 20111018 PHP console migrate:rollback -v
执行回滚操作
# PHP think migrate:rollback PHP Warning: Module 'redis' already loaded in UnkNown on line 0 == 20190804032741 Video: reverting == 20190804032741 Video: reverted 0.1992s All Done. Took 0.6151s
MysqL> desc iot_video; 1146 - Table 'iot.tinywan.com.iot_video' doesn't exist
MysqL> select * from iot_migrations; Empty set
iot_migrations 表中的数据也不存在,一并 删除了
新增表字段
对表进行二次操作,不能在同一个脚本中二次编辑,只能新建脚本。
Video
表增加字段如下
字段 | 类型 | 说明 |
---|---|---|
upload_time | int(11) | 上传时间 |
user_id | int(11) | 上传用户ID |
创建新脚本
# PHP think migrate:create Video2 created ./database/migrations/20190804082737_video2.PHP
table('video'); $table->addColumn('upload_time', 'string', ['limit' => 11, 'null' => false,'comment'=>'上传时间']) ->addColumn('user_id', 'string', ['limit' => 11, 'null' => false,'comment'=>'上传用户ID']) ->save(); } }
数据迁移
# PHP think migrate:run == 20190804082737 Video2: migrating == 20190804082737 Video2: migrated 0.3345s All Done. Took 0.7070s
查看表结构
MysqL> desc iot_video; +-------------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(16) | NO | | NULL | | | email | varchar(32) | NO | | NULL | | | password | varchar(64) | NO | | NULL | | | upload_time | varchar(11) | NO | | NULL | | | user_id | varchar(11) | NO | | NULL | | +-------------+-------------+------+-----+---------+----------------+ 6 rows in set (0.08 sec)
附录
表的方法
方法 名 | 描述 |
---|---|
setId(string $id) | 设置主键字段名 |
setPrimaryKey(string $key) | 设置主键 |
setEngine(string $engine) | 设置存储引擎,有:InnoDB,MyISAM |
setComment(string $comment) | 设置表注释 |
addTimestamps(string $createAtName, string $updateAtName) | 给表加上创建时间和编辑时间两个字段,默认字段名是:create_time,update_time |
addColumn($columnName, $type, $options) | 给表增加一个字段 |
changeColumn($columnName, $newType, $options) | 改变表的某一个字段的属性 |
create() | 创建表 |
save() | 保存表 |
rename($newTableName) | 重命名表名 |
hasTable($tableName) | exists() | 判断表是否存在 |
setIndexes(array $indexs) | 批量设置索引 |
drop() | 删除当前表 |
setForeignKeys(array $foreignKeys) | 设置外键 |
removeColumn($columnName) | 删除字段 |
renameColumn($oldName, $newName) | 字段重命名 |
insert(array $data) | 插入数据 |
列类型
类型 |
---|
biginteger |
binary |
boolean |
date |
datetime |
decimal |
float |
integer |
string |
text |
time |
timestamp |
uuid |
可选参数
参数 | 说明 |
---|---|
limit | 长度限制,整数 |
length | 同 limit ,整数 |
default | 默认值,mixed |
null | 是否可空,bool |
after | 在哪个字段后 |
comment | 注释 |
下面是针对 decimal 类型:
参数 | 说明 |
---|---|
precision | 长度,整数 |
scale | 小数位长度,整数 |
signed | 是否无符号,bool |
下面是针对 enum 和 set 类型:
参数 | 说明 |
---|---|
values | 默认值 |