在 Ubuntu 使用 Doctrine2+migrations 記錄

edited 十月 2013 in 程式架構
其實是因為想要用 Doctrine2 的 migrations 功能,雖然 Doctrine1 就有這樣的功能,但是人總是...

也同時要抱怨, cakephp 的 migration plugin 是個非常陽春的東西,不建議使用(雖然用的人也不多),使用了一陣子發現很容易遇到欄位類型不支援的瓶頸。

1. 在官方網站[1]下載 DoctrineORM-2.1.1-full.tar.gz ,解壓縮到 /home/kiang/bin/doctrine-orm
[email protected]:~/bin$ ls doctrine-orm/
bin  Doctrine  LICENSE
2. 下載 migrations 最新版本,將對應目錄移動到 DBAL 中
svn export http://svn.github.com/doctrine/migrations.git migrations
cp -R migrations/lib/Doctrine/DBAL/Migrations /home/kiang/bin/doctrine-orm/Doctrine/DBAL/
3. 參考文件說明[2],在 Doctrine/ORM/Tools/Console/ConsoleRunner.php 的 function addCommands() 加入
static public function addCommands(Application $cli) {
        $cli->addCommands(array(

...

            // Migrations Commands
            new \Doctrine\DBAL\Migrations\Tools\Console\Command\DiffCommand(),
            new \Doctrine\DBAL\Migrations\Tools\Console\Command\ExecuteCommand(),
            new \Doctrine\DBAL\Migrations\Tools\Console\Command\GenerateCommand(),
            new \Doctrine\DBAL\Migrations\Tools\Console\Command\MigrateCommand(),
            new \Doctrine\DBAL\Migrations\Tools\Console\Command\StatusCommand(),
            new \Doctrine\DBAL\Migrations\Tools\Console\Command\VersionCommand()
        ));
    }

4. 建立 bin/doctrine2 ,並且透過 chmod 755 設定為可以執行
#!/usr/bin/env php
<?php

include('doctrine-orm/bin/doctrine.php');

6. 在 doctrine-orm/bin/doctrine.php 加入 include_path 設定
ini_set('include_path',ini_get('include_path').':/home/kiang/bin/doctrine-orm');
7. 在自己的專案目錄建立一個 cli-config.php ,放入下面內容:
<?php

require_once 'Doctrine/Common/ClassLoader.php';

$classLoader = new \Doctrine\Common\ClassLoader('Entities', __DIR__);
$classLoader->register();

$classLoader = new \Doctrine\Common\ClassLoader('Proxies', __DIR__);
$classLoader->register();

$config = new \Doctrine\ORM\Configuration();
$config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ArrayCache);
$config->setProxyDir(__DIR__ . '/Proxies');
$config->setProxyNamespace('Proxies');
$driver = new \Doctrine\ORM\Mapping\Driver\YamlDriver($path . '/doctrine2/default/yml');
$config->setMetadataDriverImpl($driver);

$connectionOptions = array(
    'driver' => 'pdo_pgsql',
    'host' => '主機',
    'user' => '使用者',
    'password' => '密碼',
    'dbname' => '資料庫',
);

$em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config);

$helperSet = new \Symfony\Component\Console\Helper\HelperSet(array(
            'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()),
            'dialog' => new \Symfony\Component\Console\Helper\DialogHelper(),
            'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em)
        ));

8. 接著就可以在自己的專案目錄執行指令,我會透過下面指令產生資料表描述檔
doctrine2 orm:convert-mapping --namespace="Entities\\\" --from-database yml yml
doctrine2 orm:generate-entities .
doctrine2 migrations:diff --configuration="db.yml"

9. db.yml 內容:
---
name: MyMigrations
migrations_namespace: MyMigrations 
table_name: migration_version
migrations_directory: migrations

由於 Doctrine2 的習慣是先修改資料表定義檔,接著套用到資料表,因此一般的習慣操作是
1. 修改 yml 中的資料表定義
2. 透過 orm:generate-entities 更新 models
3. 透過 migrations:diff 產生版本記錄
4. 透過 migrations:migration 將異動套用到資料表中

對於既有程式的資料庫,我的作法是先以現有資料庫產生 yml & models ,然後暫時將設定指向一個空的資料庫,透過 migration 產生版本檔,然後再改回去。而如果是先直接修改了資料表,我會先將設定指向一個空的資料庫,透過 orm:schema-tool:create 建立一個修改前的架構副本,然後設定改回新資料庫產生新的 yml & models ,接著再指向副本產生 migration 版本,然後改回原有設定以及刪除副本

[1] http://www.doctrine-project.org/projects/orm/download
[2] http://www.doctrine-project.org/projects/migrations/2.0/docs/reference/introduction/en

原始討論: http://twpug.net/x/modules/newbb/viewtopic.php?topic_id=6300

評論

  • edited 九月 2011
    上面 --namespace="Entities 後面斜線有兩條,討論區吃掉其中一條...

    另外就是透過 migrations 產生的版本檔會有很多關於 sequences 與 constraints 的雜訊(PostgreSQL既有資料庫),也許將資料表結構都透過它管理會比較單純,自行調整資料表後進行更新的操作會比較多問題。

    它最大的好處是可以自動比對資料表與定義檔的差異,在多個執行環境間運作時比較不會有因為欄位定義不同步的問題
  • edited 九月 2011
Sign In or Register to comment.