场景及优势
熟悉Symfony框架之后,深刻感受到框架集成的ORM组件Doctrine2的强大之处,其中附带的数据迁移也十分方便。Doctrine2是使用Doctrine DBAL组件把代码里面的表结构与实际数据库中的表结构进行对比的方式进行数据迁移。这种方式比之前版本管理的方式更加精准也更方便。
Symfony框架是自身ORM组件支持,但是很多项目并没有使用其中的ORM功能,或者有自己的ORM组件,又该如何集成diff方式的迁移呢?下面我们就来完成这个任务。
源码解析
在研究组件源码时,发现一个类:Doctrine\DBAL\Migrations\Provider\SchemaDiffProvider
,其中getSqlDiffToMigrate
方法就是我们编写diff脚本的关键。
/**
* @param Schema $fromSchema
* @param Schema $toSchema
* @return string[]
*/
public function getSqlDiffToMigrate(Schema $fromSchema, Schema $toSchema)
{
return $fromSchema->getMigrateToSql($toSchema, $this->platform);
}
该方法通过传入的两个入参(fromSchema和toSchema),来对比旧数据结构和新数据结构的差异,最后返回相关的sql语句。那么我们只要拿到现有数据库中的表结构,以及代码里面的表结构,就能实现diff方式的数据迁移了。
获取现有数据库的表结构可以通过上面的createFromSchema
方法直接获取。
然后我们需要把数据结构写入代码,再从代码中获取实时的表结构,最后diff。
编写diff脚本
首先在项目创建diff文件,并赋予执行权限。之后是根据上面的思路来编写脚本,以下是完整代码示例:
#!/usr/bin/env php
<?php
require_once 'vendor/autoload.php';
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Migrations\Provider\SchemaDiffProvider;
use Doctrine\DBAL\Schema\MySqlSchemaManager;
use Doctrine\DBAL\Schema\Schema;