https://www.jianshu.com/p/5daa61fb3d46
## 通过本文你可以学到:
* Migration初识
* thinkphp5 使用 Migration
## Migration 初识
**什么是Migration?**
migration用谷歌翻译是**移民**的意思,在PHP中我们将它理解为**迁移**,将Migration用在数据库上就理解为**数据库迁移**咯。在migration开发之前,我们都是手写SQL创建表语句,创建成功之后需要手动在数据库执行,项目初始化光数据库的创建就花费很多时间。另外在多人团队开发中,如果要求每个开发人员都在本地使用数据库那么我们通常都是将数据库备份成SQL文件互相传递,这还并不是很繁琐,繁琐的在于如果数据库某个表的字段出现变动那么就需要将这个变动的SQL语句传给每个开发小伙伴让他们在本地都手动的更新下,一次可以这样,但是多次呢?我想在开发团队中这种事情肯定让人头疼咯,所以migration就诞生咯。Migration就是一些管理数据库结构的文件,这些文件其实都是抽象化的SQL,可以通过命令行执行而改变数据库的结构,这些文件都是存放在项目下的,随着项目版本的迭代而迭代。在开发过程中,如果一位小伙伴改动了数据库的表结构,她只需要生成一个migration文件并推送到版本控制系统中,如:Git,并通知其他小伙伴,其他小伙伴只需要pull然后在命令行执行下migration命令就可以了,简化了传统的数据库变动流程,加快项目的开发。
**Migration文件作用**
migration 文件的主要作用就是用来管理数据库的结构,其实它是一组SQL语句的抽象化,migration 文件可以创建表,删除表,增加字段,删除字段等等基本上所有的数据库操作,其实这就像你自己手动写SQL语句一样,只不过在 migration 中你不需要手动的写SQL语句,只需要按照它的规则语法调用一下就可以啦。
## thinkphp5 使用 migration
`thinkphp5` 为开发者提供了一整套的 migration 解决方案,不过默认情况下 migration 是没有安装的,需要我们手动安装。将工作目录切换到tp5项目下,执行:
~~~
composer require topthink/think-migration
~~~
安装成功之后,我们执行:
~~~
php think
~~~
会看到:
![](//upload-images.jianshu.io/upload_images/4047909-27bc7d89a67d8ab0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/595/format/webp)
thinkphp5 migration工具
> 从图中我们可以看到 migration 和 seed,本文中我们只讲解 migration, seed将会在下节讲解。
### create 命令
~~~
php think migrate:create TableName
~~~
TableName 格式:首字母大写的驼峰法。该命令是用来创建一个 migration 文件,比如这里我们创建一个 User 的 migration 文件:
~~~
php think migrate:create Users
~~~
migration 初次执行
第一次执行 Migraton 它会提示一些信息,这里全部统一 `yes` 就可以啦。创建成功如下:
![](//upload-images.jianshu.io/upload_images/4047909-ec6a63f95abc52fd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/530/format/webp)
migration 创建成功
在项目的根目录下多了一个 database 目录,其目录结构如下:
![](//upload-images.jianshu.io/upload_images/4047909-fceadcc1296c71aa.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/462/format/webp)
migration 目录结构
有一个Migration文件夹,该文件夹就是用来存放 Migration 文件,打开可以看到我们刚才创建的 User 的 migration 文件:
![](//upload-images.jianshu.io/upload_images/4047909-96ed4504c64a640c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/553/format/webp)
UserMigration 文件
> 有没有注意它的文件名格式?是这样的:时间 + 随机数 + \_ + 文件名。为什么这样设置?当然有它的道理啦,深入学习你就知道啦!
文件创建好之后,我们来看下它的内容:
~~~
<?php
use think\migration\Migrator;
use think\migration\db\Column;
class Users 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()
{
}
}
~~~
文件结构很简单,就一个类,但是怎么使用它呢?下面看我举一个 DEMO,这里我需要给我上面创建的 User 文件增加创建 users 表的功能,我该这样做:
**users 表结构如下:**
| 字段 | 类型 | 注释 |
| --- | --- | --- |
| `id` | `int(11)` | 主键 |
| `nickname` | `varchar(16)` | 呢称 |
| `email` | `varchar(32)` | 邮箱 |
| `password` | `varchar(64)` | 密码 |
删除默认自带的 `change` 方法,创建 `up()` 方法和 `down()` 方法。`up()` 方法是在执行 `run` 命令执行的,`down()` 是在执行 `rollback` 命令执行的。
`up()` 方法如下:
~~~
public function up()
{
$table = $this->table('users');
$table->addColumn('nickname', 'string', ['limit' => 16, 'null' => false])
->addColumn('email', 'string', ['limit' => 32, 'null' => false])
->addColumn('password', 'string', ['limit' => 64, 'null' => false])
->create();
}
~~~
`down()` 方法如下:
~~~
public function down()
{
$this->dropTable('users');
}
~~~
文件整体内容如下:
~~~
<?php
use think\migration\Migrator;
use think\migration\db\Column;
class Users extends Migrator
{
public function up()
{
$table = $this->table('users');
$table->addColumn('nickname', 'string', ['limit' => 16, 'null' => false])
->addColumn('email', 'string', ['limit' => 32, 'null' => false])
->addColumn('password', 'string', ['limit' => 64, 'null' => false])
->create();
}
public function down()
{
$this->dropTable('users');
}
}
~~~
这样,一个可以创建 users 表的 migration 文件就创建完毕了,接下来,我们来学习下一个命令。
### run 命令
migration 文件创建完毕,还需要执行 `run` 命令才可以修改数据库:
> 注意,执行此步骤之前请正确配置了 `application/database.php` 。
~~~
php think migrate:run
~~~
执行成功之后,查看数据库:
![](//upload-images.jianshu.io/upload_images/4047909-4e7515cb8af39b66.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/461/format/webp)
执行 run 命令之后
users 表结构如下:
![](//upload-images.jianshu.io/upload_images/4047909-c9befb6e0d6deea7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/576/format/webp)
users 表结构
> 可能有的小伙伴注意到,之前我定义了 migration 只指定了 `nickname`, `email`, `password` 三个字段,但是执行 `run` 命令创建的表中有四个字段,多了一个 `id` 主键?这是 `thinkphp5` 为我们默认添加的!小伙伴注意啦!如果你的主键字段名为 `id` 就不需要自己手动的指定啦!!!
### rollback 命令
现在呢,我突然不想创建 users 表啦,那怎么办呢?`thinkphp5` 为我们提供了回滚的命令:
~~~
php think migrate:rollback
~~~
该命令默认会回滚所有的已执行的migration文件,也就一夜回到解放前啦。
### status 命令
~~~
php think migrate:status
~~~
执行该命令结果如下:
![](//upload-images.jianshu.io/upload_images/4047909-e4aba2197c3e76c5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/569/format/webp)
执行 status 命令的结果
列表的形式展示了 migration 的执行情况。
### breakpoint 命令
`rollback` 默认是回滚全部的 `migration` 操作,但是项目开发中每个表中都需要一些模拟的数据,如果回滚所有的 migration, 那么表中的模拟数据全都删除了,重新执行 `run` 之后又需要重新填充数据,那就非常的麻烦咯,这显然不是我们想要得。所以,断点机制就是解决这个问题。它允许我们在创建某个表之后打上断点,这样 `rollback` 执行到这个表的时候如果是断点就停止继续运行下去了(得排除强制删除的情况)。具体命令如下:
~~~
php think migrate:breakpoint
~~~
举个例子,我首先创建了 UserMigration 文件,且执行了 `run` 命令,users 表也创建了,这个时候呢,老板说,users 的表结构设计的非常合理,暂时就这么定了!此时:
#### 一无所知【不了解断点机制】
首先,我在 users 表中填充个了 500 个用户,完成一系列的测试后,接下来我着手创建 ArticleMigration 文件,并执行了 `run` 在数据库创建了 `articles` 表,但是由于一些原因,必须得删除这个 `articles` 表,于是我执行了 `rollback` 命令,就这样数据库给清空了...于是老板
![](//upload-images.jianshu.io/upload_images/4047909-9bf1909f9d222d95.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700/format/webp)
搞事情
我也是:
![](//upload-images.jianshu.io/upload_images/4047909-dbeffa87a9598321.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/370/format/webp)
一脸懵B
#### 早有准备【了解断点机制】
执行了:
~~~
php think migrate:breakpoint
~~~
之后接着下面得操作,接下来同样出现错误,但是完美的解决。
![](//upload-images.jianshu.io/upload_images/4047909-58d99b09733255d5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/427/format/webp)
走向人生巅峰
**Q:那怎么取消断点呢?**
A:再执行一次 `breakpoint` 就可以啦。
好了今天的教程就到这里啦。此篇是小滕的《Thinkphp5入门系列课程》第十一课:Migration(一)。
喜欢的给个订阅呗!
**由于作者水平有限,如有错误请欢迎指正。**
作者:小滕Tt
链接:https://www.jianshu.com/p/5daa61fb3d46
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。