DoctrineMigrationsBundle帮助我们将实体的变化反映到数据库中,这样我们就不需要手动操作了。它将你的实体与你的数据库进行比较,因此在运行diff 命令后,你的实体中的任何更新都会出现在你的迁移文件中。它的工作方式如下:
-
如果数据库中有一个表,但是你在应用程序中删除了它的实体类,那么迁移也会在数据库中删除这个表。
-
如果你在你的应用程序中创建了一个新的实体,但是它的表在数据库中还不存在,迁移也会创建相关的表。
-
如果你对你的应用程序中的一个实体做了任何改动,迁移也会更新数据库中的相关表。
这里的关键点是,在你运行diff 命令来创建迁移文件之前,要确保这些变化还没有在数据库中出现,否则diff 命令将无法看到这些变化,最终你将得到一个空的迁移文件。
注意:如果你是第一次运行迁移过程,迁移命令将在数据库中创建migration_versions 表。之后,它将在其中插入迁移版本。
我们的例子
我在数据库中有一个app_user 表,但是在我的应用程序中删除了AppUser 实体,所以迁移时也应该删除数据库中的app_user 表。然后我在我的应用程序中添加了一个新的实体,叫做Customer ,但是这个表在数据库中还不存在,所以迁移也应该在数据库中创建customer 表。
编译器
运行composer require doctrine/doctrine-migrations-bundle "^1.3" ,安装DoctrineMigrationsBundle,并在AppKernel.php文件中添加new Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle(), 。
配置
#config.yml
doctrine_migrations:
dir_name: "%kernel.root_dir%/DoctrineMigrations"
namespace: CustomerBundle
table_name: migration_versions
name: Application Migrations
organize_migrations: false
数据库
目前我们在数据库中只有app_user 表。
mysql> SHOW TABLES;
+------------------+
| Tables_in_common |
+------------------+
| api_user |
+------------------+
1 row in set (0.00 sec)
客户实体
创建以下实体。我删除了注释、设置器和获取器方法,以保持代码的简短,但显然你必须拥有它们。
namespace CustomerBundle\Entity;
class Customer
{
private $id;
private $name;
private $dob;
}
创建迁移文件
$ php bin/console doctrine:migrations:diff
Generated new migration class to "/var/www/html/symfony/common/app/DoctrineMigrations/Version20171208210144.php" from schema differences.
$ cat app/DoctrineMigrations/Version20171208210144.php
namespace CustomerBundle;
use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
/**
* Auto-generated Migration: Please modify to your needs!
*/
class Version20171208210144 extends AbstractMigration
{
public function up(Schema $schema)
{
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('CREATE TABLE customer (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(50) NOT NULL, dob DATETIME NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB');
$this->addSql('DROP TABLE api_user');
}
public function down(Schema $schema)
{
// this down() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('CREATE TABLE api_user (id INT AUTO_INCREMENT NOT NULL, api_key VARCHAR(36) NOT NULL COLLATE utf8_unicode_ci, roles LONGTEXT NOT NULL COLLATE utf8_unicode_ci COMMENT \'(DC2Type:array)\', UNIQUE INDEX unq_api_key (api_key), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB');
$this->addSql('DROP TABLE customer');
}
}
执行迁移
$ php bin/console doctrine:migrations:migrate --no-interaction
Application Migrations
Migrating up to 20171208210144 from 0
++ migrating 20171208210144
-> CREATE TABLE customer (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(50) NOT NULL, dob DATETIME NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB
-> DROP TABLE api_user
++ migrated (0.41s)
------------------------
++ finished in 0.41s
++ 1 migrations executed
++ 2 sql queries
数据库
mysql> SHOW TABLES;
+--------------------+
| Tables_in_common |
+--------------------+
| customer |
| migration_versions |
+--------------------+
2 rows in set (0.01 sec)
mysql> SELECT * FROM migration_versions;
+----------------+
| version |
+----------------+
| 20171208210144 |
+----------------+
1 row in set (0.00 sec)
mysql> SELECT * FROM customer;
Empty set (0.01 sec)