# ThinkPHP6数据库迁移工具
[TOC]
## 介绍
> 本篇文章均可适用于`tp5`,`tp5.1`,`tp6`.
### 依赖
~~~
composer require topthink/think-migration
~~~
### 官方文档
可以先阅读一下官方文档,再来这里看实例用法.
[数据库迁移工具](https://www.kancloud.cn/manual/thinkphp6_0/1118028)
### 有什么好处
- 数据库自动创建,数据自动初始化
- 数据库跟随代码版本保留和更新
- 一份代码,多种数据库(Mysql,Sqlite,SqlServer,PostgreSQL,MongoDb)
### 什么是数据库迁移工具
有一个库叫[Phinx](http://docs.phinx.org/en/latest/),可以用php代码建立数据表结构.
我们设计数据表的时候,可能是用图形化软件来设计,比如`MySQL-Front`,`Dbeaver`.也有可能有人直接写sql语句.还有一种方式就是用`Phinx`来设计数据表结构.
`Phinx`的用法类似如下:
~~~
<?php
use Phinx\Migration\AbstractMigration;
class CreateUserLoginsTable extends AbstractMigration
{
/**
* Change Method.
*
* More information on this method is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-change-method
*
* Uncomment this method if you would like to use it.
*/
public function change()
{
// create the table
$table = $this->table('user_logins');
$table->addColumn('user_id', 'integer')
->addColumn('created', 'datetime')
->create();
}
/**
* Migrate Up.
*/
public function up()
{
}
/**
* Migrate Down.
*/
public function down()
{
}
}
~~~
`Phinx`本身是一个完整的功能强大的类库,在ThinkPHP中,并没有依赖这个库,而是将它核心的代码二次开发成适应tp架构的`think-migration`库.
### 主要功能
- 创建数据表
- 修改数据表
- 初始化数据
## 基本用法
需要结合ThinkPHP命令行使用,有的人可能不熟悉,请先看一下文档[命令行](https://www.kancloud.cn/manual/thinkphp6_0/1037640).
### 操作一次数据库
当我们想操作一次数据库的时候,就要用命令行创建一个执行文件.
操作数据库是指:创建表,修改表.
可以在一个执行文件里操作多个表,但我个人建议,一个文件只操作一个表.
执行命令:
~~~
php think migrate:create AnyClassNameYouWant
~~~
此时会在项目下生成如下文件:
~~~
/database/migrations/20190615151716_any_class_name_you_want.php
~~~
我们要把自己对数据库的操作写到这个文件里.
### 执行操作
我们可能会创建多个文件,每个文件操作一个表,我们在每个文件里都写好数据库结构之后,就执行操作,真正的创建数据表.
执行命令:
~~~
php think migrate:run
~~~
此时数据库就会多出你刚刚操作的表,不管是创建还是更新,都已经生效了.
> 数据表的名字会有配置文件里设置的前缀
## 例子
### 定义一个`users`表
执行命令:
```
php think migrate:create CreateTableUsers
```
会生成相应的文件,修改文件内容如下:
~~~
<?php
use think\migration\Migrator;
use think\migration\db\Column;
class CreateTableUsers 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()
{
// create the table
$table = $this->table('users',array('engine'=>'MyISAM'));
$table->addColumn('username', 'string',array('limit' => 15,'default'=>'','comment'=>'用户名,登陆使用'))
->addColumn('password', 'string',array('limit' => 32,'default'=>md5('123456'),'comment'=>'用户密码'))
->addColumn('login_status', 'boolean',array('limit' => 1,'default'=>0,'comment'=>'登陆状态'))
->addColumn('login_code', 'string',array('limit' => 32,'default'=>0,'comment'=>'排他性登陆标识'))
->addColumn('last_login_ip', 'integer',array('limit' => 11,'default'=>0,'comment'=>'最后登录IP'))
->addColumn('last_login_time', 'datetime',array('default'=>0,'comment'=>'最后登录时间'))
->addColumn('is_delete', 'boolean',array('limit' => 1,'default'=>0,'comment'=>'删除状态,1已删除'))
->addIndex(array('username'), array('unique' => true))
->create();
}
}
~~~
在上面这个文件中,会定义一个`users`表,给这个表添加字段`addColumn`,给这个表添加索引`addIndex`,最后执行创建方法`create`.
### 创建这个表
执行命令:
```
php think migrate:run
```
此时数据库便创建了这个表.
### 修改这个表
现在给这个表增加`avatar`字段
新建一个执行文,
执行命令:
```
php think migrate:create UpdateTableUsers
```
修改内容文件如下:
~~~
<?php
use think\migration\Migrator;
use think\migration\db\Column;
class CreateTableUsers 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()
{
// create the table
$table = $this->table('users');
$table->addColumn('avatar', 'string',array('limit' => 100,'default'=>'','comment'=>'用户头像'))
$table->update();
}
}
~~~
执行命令,写入数据库:
```
php think migrate:run
```
此时`users`表就多了一个`avatar`字段.
> 语法具体可参考手册或`Phinx`文档.
### 其他操作
如果你希望给删除字段,重命名字段,删除表等其他操作,不能写在`change`方法里.
`change`方法里的操作都是可以自动升级/还原的,只支持一部分操作.
如果你不打算使用这个特性,那就可以随便使用所有方法,具体的可以参考`Phinx`文档.