ご無沙汰しています。ポリドッグです。
前回DoctrineMigrationsBundleで複数データーベース対応できるようにしてみたを書きましたが、今回はその追記というか、
前回の記事のアプローチが間違ってたので、最近の僕の対応方法をご紹介しようと思います。
前回のアプローチにはどのような問題があっのか?
そもそもとしてMySQL用、PostgreSQL用のAbstractMigrationクラスを作成する
ってことを考えている時点で負け組なんですよね。
まあ前回の記事書いた当時は、mysqlとPostgreSQLを併用していたので、あの方法でも対応できたんですが、、、mysqlで複数コネクションを持ちたいって事も多々あるんですよね。
Symfony的は複数コネクションをどう分けているのか。
Symfony的には複数のデータベースのコネクションを持つ時はDBALのconnections
で管理してますよね。
config.yml
とかにこんな感じに書いていると思います。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
doctrine:
dbal:
default_connection: default
connections:
default:
driver: "%database_driver%"
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
log:
driver: "%log_database_driver%"
host: "%log_database_host%"
port: "%log_database_port%"
dbname: "%log_database_name%"
user: "%log_database_user%"
password: "%log_database_password%"
charset: UTF8
|
つまり、マイグレーションでもdefault
やlog
といったコネクション名を指定したらいい感じになってくれるのが望ましいんですよ。
解決策
正しい解決策なのかは、わかりませんが本家のドキュメントを見ていると
ContainerAwareInterface
をimplements
すれば、サービコンテナを利用することができます。
ということは、コンテナから対象のデータベースのコネクションオブジェクトを取得してAbstractMigration
側でもっているコネクションと一致すればマイグレーションを実行するといった感じの実装にしてあげればいいんですよね。
ということで以下のようにAbstractMigration
を継承したCustomMigration
クラスを作成します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
<?php
namespace AppBundle\Doctrine\DBAL\Migrations;
use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
abstract class CustomMigration extends AbstractMigration implements ContainerAwareInterface
{
/**
* @var ContainerInterface
*/
protected $container;
protected $targetConnection = 'default';
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
public function preUp(Schema $schema)
{
$this->skipIf($this->container->get("doctrine.dbal.{$this->targetConnection}_connection") !== $this->connection, 'other connection database name');
}
public function preDown(Schema $schema)
{
$this->skipIf($this->container->get("doctrine.dbal.{$this->targetConnection}_connection") !== $this->connection, 'other connection database name');
}
}
|
skipIf
メソッドとpreUp
,preDown
メソッドを活用してCustomMigrationクラスを作成しました。
AbstractMigration側で持っているコネクションとCustomMigration::$targetConnection
で期待しているコネクションが一致してなければ、マイグレーションをスキップするようにしています。
これによって、うまくマイグレーションが実行できるようになります。
targetConnection
のクラス変数にコネクション名を入れれば、あとはいい感じにマイグレーションできるわけです。
最後に
どのマイグレーションファイルがどのコネクション用なのかも、ファイルを見てわかりやすいのでこの方法はかなりおすすめですよ!
他にもやり方があるような気もするので、良い方法をご存知の方がいらっしゃいましたら教えてくださいw
おしまい。