PHPで使えるDBマイグレーションツール phpmig

dbdeploy 並みにシンプルで、PHP でわりと汎用的に使えるマイグレーションツールはないかと探しているところ。

初めは、
http://www.ryuzee.com/contents/blog/4268
を参考に Doctrine1 を試してみたのだが、ORM用ファイルがたくさん生成されるのが気に入らなかった。また、Doctrin1 独特の制約もあり、イマイチ使いづらい感じがした。

ググってみたら、PHP のマイクロフレームワーク Silex で使うと良さそうなDBマイグレーションツールを見つけた。

https://github.com/davedevelopment/phpmig
http://davedevelopment.co.uk/2011/11/01/phpmig-simple-migrations-for-php.html

DB接続に Doctrine の DBAL や Zend_DB などが使えるとのこと。

インストール

sudo pear config-set auto_discover 1
sudo pear channel-discover pear.atstsolutions.co.uk
sudo pear install atst/phpmig-alpha

初期化

phpmig init

カレントディレクトリに migrations ディレクトリと phpmig.php が生成される。
以後は、phpmig.php が設定ファイル(bootstrap) として読み込まれる。

生成された phpmig.php:

<?php

use \Phpmig\Adapter,
    \Phpmig\Pimple\Pimple;

$container = new Pimple();

$container['phpmig.adapter'] = $container->share(function() {
    // replace this with a better Phpmig\Adapter\AdapterInterface
    return new Adapter\File\Flat(__DIR__ . DIRECTORY_SEPARATOR . 'migrations/.migrations.log');
});

$container['phpmig.migrations'] = function() {
    return glob(__DIR__ . DIRECTORY_SEPARATOR . 'migrations/*.php');
};

return $container;

まず $container を生成し、$container['phpmig.adapter'], $container['phpmig.migrations']
を環境に合わせて設定しているみたい。$container['db'] にDBオブジェクトを設定するのが定石のよう。


$container['phpmig.adapter'] は、AdapterInterface を実装したオブジェクトを設定しているっぽい。
AdapterInterface は、DBのバージョンを管理するインターフェースのようだ。標準で用意されている Adapter\File\Flat クラスは、テキストファイル形式で管理するもの。他には、Adapter\Doctrine\DBAL, Adapter\Zend\Db などが用意されている。

$container['phpmig.migrations'] は、マイグレーションファイルのリストを格納しているっぽい。

ステータス確認

phpmig status

マイグレーションファイルの生成

 phpmig generate CreateFirstTable ./migrations

$this->Container() で phpmig.php で生成したコンテナオブジェクトを取得してるわけだ。up(), down() メソッドが呼ばれたときに、コンテナに事前に設定している必要なもの(DBオブジェクトなど)を取り出して目的を達成する。

<?php

use Phpmig\Migration\Migration;

class CreateFirstTable extends Migration
{
    /**
     * Do the migration
     */
    public function up()
    {
        $container = $this->getContainer();
        $container['db']->query("
            CREATE TABLE `user` (`id` INTEGER,`name` TEXT, PRIMARY KEY (`id`));
        ");
    }

    /**
     * Undo the migration
     */
    public function down()
    {
        $container = $this->getContainer();
        $container['db']->query("DROP TABLE IF EXISTS `user`;");
    }
}

マイグレーション実行

 phpmig migrate

ロールバック

 phpmig rollback