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

    images

    从图中我们可以看到 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 文件:

    images

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

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

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

    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');
    }
    

    文件整体内容

    <?php
    
    use thinkmigrationMigrator;
    use thinkmigrationdbColumn;
    
    class Video extends Migrator
    {
    	// migrate:run 时执行
    	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();
    	}
    
        // 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设计表结构查看注释

    images

    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 文件内容

    <?php
    
    use thinkmigrationMigrator;
    
    class Video2 extends Migrator
    {
        public function up()
        {
            $table = $this->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 默认值
  • 相关阅读:
    Shell编程之数值运算(二) Theletter
    Shell编程检测某个服务是否运行实例 Theletter
    Shell编程之条件测试与比较(详解) Theletter
    eclipse中svn提交时报Previous operation has not finished; run 'cleanup' if it was interrupted错误的解决方法
    Jsp连接打印机
    Jsp中table导出到excel
    java创建图片验证码
    java利用映射表名称反射创建实体类并赋属性值
    基于方法的LINQ语句
    opencv中cvCreateImage大图片时出错
  • 原文地址:https://www.cnblogs.com/tinywan/p/11298997.html
Copyright © 2020-2023  润新知