PHP系列 | ThinkPHP5数据库迁移工具 migration

了解更多,请关注微信公众号

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 命令介绍

  • migrate:breakpoint   管理断点

  • migrate:create       创建一个迁移文件

  • migrate:rollback     回滚最后一个或特定的迁移

  • migrate:run          迁移数据库

  • migrate:status       显示迁移状态

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命令查看是否安装成功

PHP系列 | ThinkPHP5数据库迁移工具 migration

从图中我们可以看到 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系列 | ThinkPHP5数据库迁移工具 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 文件增加字段

Video 表结构如下

字段 类型 说明
id int 主键
nickname varchar(16) 视频名称
email 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 命令才可以修改数据库:

注意,执行此步骤之前请正确配置了 config/database.php 。 在这里的数据库是有前缀的iot_

php think migrate:run

执行成功之后,查看数据库,多了两个表iot_migrationsiot_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, email, password 三个字段,但是执行 run 命令创建的表中有四个字段,多了一个 id 主键?这是 thinkphp5 为我们默认添加的!小伙伴注意啦!如果你的主键字段名为 id 就不需要自己手动的指定了。

iot_video设计表结构查看注释

PHP系列 | ThinkPHP5数据库迁移工具 migration

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 表中的数据也不存在,一并 删除了

新增表字段

对表进行二次操作,不能在同一个脚本中二次编辑,只能新建脚本。

下面给表iot_video增加新字段,重新生成表结构

Video 表增加字段如下

字段 类型 说明
upload_time int(11) 上传时间
user_id int(11) 上传用户ID

创建新脚本

# php think migrate:create Video2
created ./database/migrations/20190804082737_video2.php

Video2 文件内容

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 默认值
上一篇:thinkphp5支持跨域(post-get-option请求)


下一篇:Swift - 使用CollectionView实现图片Gallery画廊效果(左右滑动浏览图片)