TP5系列 | 数据库迁移工具migration

2019-08-08 22:27:11 浏览数 (1)

什么是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项目下,执行:

代码语言:javascript复制
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 文件:

代码语言:javascript复制
php think migrate:create Video

第一次执行 Migraton 它会提示一些信息,这里全部统一 yes 就可以啦。创建成功如下:

代码语言:javascript复制
# 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 文件:

文件格式命名规则:时间 随机数 _ 文件名

文件创建好之后,来看下它的内容:

代码语言:javascript复制
<?php

use thinkmigrationMigrator;
use thinkmigrationdbColumn;

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() 方法如下 :

代码语言:javascript复制
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() 方法如下:

代码语言:javascript复制
public function down()
{
	$this->dropTable('video');
}

文件整体内容

代码语言:javascript复制
<?php

use thinkmigrationMigrator;
use thinkmigrationdbColumn;

class Video extends Migrator
{
	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();
	}

	public function down()
	{
		$this->dropTable('video');
	}
}

这样,一个可以创建 video 表的 migration 文件就创建完毕了,接下来,来学习下一个命令。

run 命令

migration 文件创建完毕,还需要执行 run 命令才可以修改数据库:

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

代码语言:javascript复制
php think migrate:run

执行成功之后,查看数据库,多了两个表iot_migrationsiot_video

iot_video表结构如下

代码语言:javascript复制
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设计表结构查看注释

iot_migrations表中的内容是什么?

代码语言:javascript复制
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是和文件名一一对应的

status 命令

代码语言:javascript复制
# 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 的执行情况

breakpoint 命令

RedisSubscribe 类

代码语言:javascript复制
class RedisSubscribe
{
    public function subscribe()
    {
        $redis = BaseRedis::plocal();
        $redis->setOption(Redis::OPT_READ_TIMEOUT, -1);
        // 这里是键空间过期是选用的1号数据库
        $redis->psubscribe(array('__keyevent@1__:expired'), function ($redis, $pattern, $chan, $msg) {
            Log::info('[订阅事件] 过期KEY ' . $msg);
            $originData = explode(':', $msg);
            $event_key = $originData[1] ?? '0';
            $event_status = $originData[0] ?? '0';
            // 根据事件类型做出业务处理既可
        });
    }
}

$msg 变量就是一个Redis的键key,如,订单过期时间(订单多长时间后延迟取消),可以设置键:S20190722100001:1001 1、S20190722100001 表示订单号 2、1001表示是具体是哪个订单事件。 3、如:1001表示订单过期(二维码过期不能够进行支付,失效二维码),1002表示多长时间之内(30分钟之内之未支付取消)未支付需要取消的订单事件。

0 人点赞