Widgets

最近剛好手邊案子與客戶端的技術諮詢都遇當類似的狀況(之前舊的程式碼用了 doctrine 但新的案子或專案進度改用 Zend Framework 為基礎),有鑑於之前在網路上搜尋了一些文件,大多都是將 doctrine 進 Zend Framework 1.7 之前的版本,當今 Zend Framework 已經悄然來到 1.10.x 因此趁著晚餐前的時間把一些筆記整理出來跟大家分享 :)


事前準備/閱讀/參考資料


想法: 直覺


最一開始的直覺想法是準備一個環境讓 Zend Framework 認得 Doctrine (的存在),也方便我們 (Developer) 在 Controllers/Actions 或 Models 裡頭隨時可以呼叫 Doctrine 的各種功能。那這樣的話,直接請 Zend Framework 的 autoloader (Zend_Loader_Autoloader) 來幫忙吧。


(在這篇筆記裡頭先只有考慮最單純的 Zend Framework 專案環境 (因為待會要去吃晚餐了^^;) 所以專案裡頭有多個 modules 的話再另外分拆 model files 囉:)


做法: 


1. 先將 Doctrine 放到 include_path 讀得到的地方。(想偷懶嗎?也想去吃晚餐嗎?如果只是想測試一下,直接整包 Doctrine/ 和 Doctrine.php 先丟到 _zf_project_/library/ 裡頭去吧。)


2. 編輯 _zf_project_/application/Bootstrap.php,指定一個 namespace 給 Zend_Loader_Autoloader。並且可以設定一些 Doctrine 的屬性進去,喔對,也包含了 dsn 連線資訊等等。(做到這邊差不多接下來就跟原本直接用 Doctrine 的設定一樣了。)


class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    protected function _initAppAutoload()
    {
        $autoloader = new Zend_Application_Module_Autoloader(array(
            'namespace' => 'App',
            'basePath'  => dirname(__FILE__),
        ));
        return $autoloader;
    }

    protected function _initDoctrine()
    {
        $this->getApplication()->getAutoloader()
                               ->pushAutoloader(array('Doctrine', 'autoload'));
        // 這邊以下就跟原本的 Doctrine 用法一樣。
        $manager = Doctrine_Manager::getInstance();
        $manager->setAttribute(Doctrine::ATTR_AUTO_ACCESSOR_OVERRIDE, true);
        $manager->setAttribute(
            Doctrine::ATTR_MODEL_LOADING,
            Doctrine::MODEL_LOADING_CONSERVATIVE,
            Doctrine_Core::ATTR_VALIDATE
        );
        $manager->setAttribute(Doctrine::ATTR_AUTOLOAD_TABLE_CLASSES, true);

        $dsn = $this->getOption('dsn');
        $conn = Doctrine_Manager::connection($dsn, 'doctrine');
        $conn->setAttribute(Doctrine::ATTR_USE_NATIVE_ENUM, true);
        return $conn;
    }
}


3. 接著在 _zf_project_/application/configs/applications.ini 裡頭放入
dsn = "mysql://db_usr:db_pwd@db_server/db_name"
4. 最後在 _zf_project_/public/index.php 中指定 models/ 的路徑。(我個人習慣在 index.php 或 applications.ini 其中之一指定路徑相關的設定值,統一放一個地方方便未來的 deployment。)

// Load Doctrine Models
Doctrine_Core::loadModels(APPLICATION_PATH . '/models/generated');
Doctrine_Core::loadModels(APPLICATION_PATH . '/models');

5. 這樣就可以跟以前一樣直接拿 Doctrine 各項功能在 Zend Framework 裡頭使用囉 :)



推薦延伸閱讀

  • Quick Start to Zend_Application_Bootstrap (Matthew)
  • Zend Framework 與 Doctrine 的官方整合有看到 Draft 文件在 Zend Framework Wiki 上,但也許在等 Doctrine2 出來一起弄 (吧)?
  • 晚餐去 (fork) !! :)

2 Comments:

  1. 您好,請問一下為何您會想將Doctrine與Zend Framework做整合呢?Zend不是已經有了Zend_Db了嗎?

    ReplyDelete
  2. @Peter: 因為組織管理時為了精簡管理幅度,所以我讓團隊工程師盡量都使用共用的套件或模組。通常我們不會只考量技術問題,而會將管理成本也一併納入做衡量。給您做參考。

    ReplyDelete

 
Top