Zend Framework 1.11.0 and Doctrine 1.2.3 and Smarty 3.0.4

懶惰許久~~ 趕快來補一下功課.
這篇主要介紹 Zend Framework 1.11.0 and Doctrine 1.2.3 and Smarty 3.0.4 的結合方式.
Doctrine 1.2.3 跟 Zend Framework 1.11.0 結合主要參考 http://pastie.org/481633 http://pastie.org/481635 使用.

目錄結構:


將之前所做Smarty整合 與Doctrine 整合需要的放在一起,不像之前在個別目錄.
如果再像之前一樣, 放在個別目錄目錄會遇到升級版本不便利性.
現在將之後要整合的東西命名為ZendX.

之後Smarty要升級只需將Smarty3目錄內容替換.

來看看application.ini

phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
includePaths.library = APPLICATION_PATH "/../library"
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
appnamespace = "Application"
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
resources.frontController.params.displayExceptions = 0
;resources.frontController.noViewRenderer = 1
resources.layout.layout = "layout"
resources.layout.layoutPath[] = APPLICATION_PATH "/layouts/scripts/"
resources.layout.viewSuffix = "tpl.htm"
resources.layout.inflectorTarget = "layouts/scripts/:script.:suffix"
autoloaderNamespaces[] = "ZendX_"
 
;Smarty3
pluginPaths.ZendX_Smarty3_Application_Resource = "ZendX/Application/Resource"
resources.smarty.script_path = APPLICATION_PATH "/"
resources.smarty.view_suffix = "tpl.htm"
resources.smarty.params.left_delimiter = "<%"
resources.smarty.params.right_delimiter = "%>"
resources.smarty.params.auto_literal = 0
resources.smarty.params.plugins_dir = APPLICATION_PATH "/../Smarty3/plugins"
resources.smarty.params.compile_dir = APPLICATION_PATH "/../tmp/compiled"
resources.smarty.helper_dirs.key[] = "Zend/View/Helper" 
resources.smarty.helper_dirs.value[] = "Zend_View_Helper_"
;如果將來需要自己的 View Helper ,可以放在這裡
resources.smarty.helper_dirs.key[] = "My/View/Helper" 
resources.smarty.helper_dirs.value[] = "My_View_Helper_"
 
;Doctrine
autoloaderNamespaces[] = "Doctrine_"
pluginPaths.ZendX_Doctrine_Application_Resource = "ZendX/Application/Resource"
resources.doctrine.connections.orm1.dsn = "mysql://user:password@hosts/db"

加入整合用的

autoloaderNamespaces[] = "ZendX_"

之前整合Smarty 未使用layout.
搞了半天發現只是要簡單的加入.

resources.layout.layout = "layout"
resources.layout.layoutPath[] = APPLICATION_PATH "/layouts/scripts/"
resources.layout.viewSuffix = "tpl.htm"
resources.layout.inflectorTarget = "layouts/scripts/:script.:suffix"

其中主要為

resources.layout.viewSuffix = "tpl.htm"
resources.layout.inflectorTarget = "layouts/scripts/:script.:suffix"

告訴ZF layout使用的目標與附檔名格式即可.

再來看看Doctrine
http://pastie.org/481633
此為主要Application Resource 內容如下

<?php
class ZendX_Doctrine_Application_Resource_Doctrine extends Zend_Application_Resource_ResourceAbstract
{
    /**
     * @var Doctrine_Manager
     */
    protected $_manager = null;
 
    /**
     * @var array
     */
    protected $_paths = array();
 
    /**
     * @var array
     */
    protected $_profilers = array();
 
    /**
     * Initialize Doctrine
     * 
     * @return bool
     */
    public function init()
    {
        Zend_Loader_Autoloader::getInstance()->setFallbackAutoloader(true);
 
        $manager = $this->getManager();
 
        if ($options = $this->getOptions()) {
            if (isset($options['paths'])) {
                $this->getPaths($options['paths']);
            }
 
            if (isset($options['attributes'])) {
                $this->getAttributes($options['attributes']);
            }
 
            if (isset($options['connections'])) {
                $this->getConnections($options['connections']);
            }
 
            if (isset($options['debug'])) {
                $this->getDebug($options['debug']);
            }
        }
 
        $registryData = array(
            'paths'     => $this->_paths,
            'profilers' => $this->_profilers,
        );
        Zend_Registry::set('doctrine', $registryData);
 
        return $manager;
    }
 
    /**
     * Retrieve manager instance
     * 
     * @return Doctrine_Manager
     */
    public function getManager()
    {
        if (null === $this->_manager) {
            try {
                $this->_manager = Doctrine_Manager::getInstance();
            } catch (Doctrine_Exception $e) {
                /** @see Zend_Application_Resource_ResourceAbstract */
                require_once 'ZendX/Doctrine/Application/Resource/Exception.php';
 
                throw new 
                    ZendX_Doctrine_Application_Resource_Exception('Unable to 
                    retrieve Doctrine_Manager instance.');
            }
        }
 
        return $this->_manager;
    }
 
    /**
     * Set global attributes
     * 
     * @param array $attributes
     * @return ZendX_Doctrine_Application_Resource_Doctrine
     */
    public function getAttributes(array $attributes = array())
    {
        foreach ($attributes as $key => $value) {
            $this->_manager->setAttribute($key, $value);
        }
 
        return $this;
    }
 
    /**
     * Lazy load connections
     * 
     * @param array $connections
     * @return ZendX_Doctrine_Application_Resource_Doctrine
     *
     * @todo Handle event listeners
     */
    public function getConnections(array $connections = array())
    {
        foreach ($connections as $name => $params) {
            if (!isset($params['dsn'])) {
                /** @see Zend_Application_Resource_ResourceAbstract */
                require_once 'ZendX/Doctrine/Application/Resource/Exception.php';
 
                throw new 
                    ZendX_Doctrine_Application_Resource_Exception('Doctrine 
                    resource dsn not present.');
            }
 
            $dsn = null;
            if (is_string($params['dsn'])) {
                $dsn = $params['dsn'];
            } elseif (is_array($params['dsn'])) {
                $dsn = $this->_buildConnectionString($params['dsn']);
            } else {
                /** @see Zend_Application_Resource_ResourceAbstract */
                require_once 'ZendX/Doctrine/Application/Resource/Exception.php';
 
                throw new 
                    ZendX_Doctrine_Application_Resource_Exception("Invalid 
                    Doctrine resource dsn format.");
            }
 
            try {
                $conn = Doctrine_Manager::connection($dsn, $name);
 
                if (isset($params['attributes'])) {
                    foreach ($params['attributes'] as $key => $value) {
                        $conn->setAttribute($key, $value);
                    }
                }
 
                if (isset($params['listeners']['connection'])) {
                    foreach ($params['listeners']['connection'] as $alias => $class) {
                        $listener = new $class();
                        $conn->addListener($listener, $alias);
 
                        if ($listener instanceof Doctrine_Connection_Profiler) {
                            $this->_profilers[] = $listener;
                        }
                    }
                }
 
                if (isset($params['listeners']['record'])) {
                    foreach ($params['listeners']['record'] as $alias => $class) {
                        $listener = new $class();
                        $conn->addRecordListener($listener, $alias);
                    }
                }
            } catch(Doctrine_Exception $e) {
                /** @see Zend_Application_Resource_ResourceAbstract */
                require_once 'ZendX/Doctrine/Application/Resource/Exception.php';
 
                throw new ZendX_Doctrine_Application_Resource_Exception("Unable 
                    to establish connection named $name to $dsn.");
            }
        }
 
        return $this;
    }
 
    /**
     * Set the debug status
     * 
     * @param  bool $debug
     * @return ZendX_Doctrine_Application_Resource_Doctrine
     */
    public function getDebug($debug = 0)
    {
        Doctrine::debug($debug);
        return $this;
    }
 
    /**
     * Set the paths array
     * 
     * @param  array $paths
     * @return ZendX_Doctrine_Application_Resource_Doctrine
     */
    public function getPaths(array $paths = array())
    {
        $this->_paths = $paths;
        return $this;
    }
 
    /**
     * Build connection string
     * 
     * @param  array $dsnData
     * @return string
     */
    private function _buildConnectionString(array $dsnData = array())
    {
        $connectionOptions = null;
        if ((isset($dsnData['options'])) || (!empty($dsnData['options']))) {
            $connectionOptions = 
                $this->_buildConnectionOptionsString($dsnData['options']);
        }
 
        return sprintf('%s://%s:%s@%s/%s?%s',
            $dsnData['adapter'],
            $dsnData['user'],
            $dsnData['pass'],
            $dsnData['hostspec'],
            $dsnData['database'],
            $connectionOptions);
    }
 
    /**
     * Build connection options string
     * 
     * @param  array $optionsData
     * @return string
     */
    private function _buildConnectionOptionsString(array $optionsData = array())
    {
        $i = 0;
        $count = count($optionsData);
        $options  = null;
 
        foreach ($optionsData as $key => $value) {
            if ($i == $count) {
                $options .= "$key=$value";
            } else {
                $options .= "$key=$value&";
            }
 
            $i++;
        }
 
        return $options;
    }
}

使用時必須在你的public/index.php 內的增加修改這段.

// Ensure library/ is on include_path
/*set_include_path(implode(PATH_SEPARATOR, array(
    realpath(APPLICATION_PATH . '/../library'),
    get_include_path(),
)));*/
/** 修改為**/
set_include_path(implode(PATH_SEPARATOR, array(
    realpath(APPLICATION_PATH . '/../library'),
    realpath(APPLICATION_PATH . '/models'),
    realpath(APPLICATION_PATH . '/models/generated'),
    get_include_path(),
)));

因為Doctrine 太強大可以引入各總sql 自定models…等等.
但是目前不太熟所以沒有針對Doctrine 做目錄規劃整合.

使用方式:
http://pastie.org/481635

1. Overview
 
Zend_Application_Resource_Doctrine is intended to provide connection
initialization and environment setup for Doctrine ORM.
 
2. References
 
Zend_Application_Resource_ResourceAbstract
 
3. Component Requirements, Constraints, and Acceptance Criteria
 
This component will require the use of the fallback autoload mechanism.
TESTS >>> check autoloader property
 
This will component will store an array of paths and profilers to the registry
using the key 'doctrine'.
 
This component will allow specification of an array of paths to be added to
the registry. Typically these would include paths necessary to execute
Doctrine tasks.
TESTS >>> check for existence of registry key if one or more paths are set.
 
This component will provide lazy loading of multiple connections.
TESTS >>> check Doctrine_Manager connections
 
This component will allow specification of global Doctrine environment
settings.
TESTS >>> check Doctrine settings
 
This component will allow specification of connection level environment
settings.
TESTS >>> check Doctrine settings
 
This component will allow specification of connection and record event
listeners for connections. Modifying the existing environment is not
supported.
TESTS >>> check Doctrine_Connection properties
 
Unsupported Features:
 
- Cacheing
 
- Persistent connections. See
  http://groups.google.com/group/doctrine-user/browse_thread/thread/19700db17bfe5470/eef3690beeffb72e?
 
- Special cases of array, as opposed to string, properties attribute properties:
resources.doctrine.attributes.default_column_options.length = 255
resources.doctrine.attributes.default_column_options.notnull = 1
resources.doctrine.attributes.default_column_options.type = "string"
---
resources.doctrine.attributes.default_identifier_options.length = 16
resources.doctrine.attributes.default_identifier_options.name = "%s_id"
resources.doctrine.attributes.default_identifier_options.type = "string"
 
4. Dependencies on Other Framework Components
 
Doctrine
 
Zend_Application
 
Zend_Config
 
5. Theory of Operation
 
Users will specify paths, data source names, attribute and event listeners in
application.ini. Resources will be autoloaded when using Zend_Application.
 
6. Milestones / Tasks
 
7. Class Index
 
ZendX_Doctrine_Application_Resource_Doctrine
 
8. Use Cases
 
------------------------------
Base Setup
------------------------------
Setup autoloader and plugin path in application/configs/application.ini:
 
autoloadernamespaces.0 = "Doctrine"
 
pluginpaths.ZendX_Doctrine_Application_Resource= "ZendX/Doctrine/Application/Resource"
 
Add paths to models and generated models in public/index.php
set_include_path(implode(PATH_SEPARATOR, array(
    realpath(APPLICATION_PATH . '/../library'),
    realpath(APPLICATION_PATH . '/models'),
    realpath(APPLICATION_PATH . '/models/generated'),
    get_include_path(),
)));
 
------------------------------
Set Debug Status
是否開啟debug
------------------------------
resources.doctrine.debug = 1
 
------------------------------
Use Single Connection (string)
單一連接(使用dsn字串)
------------------------------
resources.doctrine.connections.cx1.dsn = "mysql://user:pass@host/cx1"
 
------------------------------
Use Multiple Connections (string)
多重連接(使用dsn字串)
------------------------------
resources.doctrine.connections.cx1.dsn = "mysql://user:pass@host/cx1"
resources.doctrine.connections.cx2.dsn = "mysql://user:pass@host/cx2"
 
------------------------------
Use Single Connection (array)
單一連接
------------------------------
resources.doctrine.connections.cx1.dsn.adapter = mysql
resources.doctrine.connections.cx1.dsn.user = user
resources.doctrine.connections.cx1.dsn.pass = pass
resources.doctrine.connections.cx1.dsn.hostspec = host
resources.doctrine.connections.cx1.dsn.database = cx1
resources.doctrine.connections.cx1.dsn.options.option1 = value
resources.doctrine.connections.cx1.dsn.options.option2 = value
 
------------------------------
Use Multiple Connections (array)
多重連接
------------------------------
resources.doctrine.connections.cx1.dsn.adapter = mysql
resources.doctrine.connections.cx1.dsn.user = user
resources.doctrine.connections.cx1.dsn.pass = pass
resources.doctrine.connections.cx1.dsn.hostspec = host
resources.doctrine.connections.cx1.dsn.database = cx1
resources.doctrine.connections.cx1.dsn.options.option1 = value
resources.doctrine.connections.cx1.dsn.options.option2 = value
 
resources.doctrine.connections.cx2.dsn.adapter = mysql
resources.doctrine.connections.cx2.dsn.user = user
resources.doctrine.connections.cx2.dsn.pass = pass
resources.doctrine.connections.cx2.dsn.hostspec = host
resources.doctrine.connections.cx2.dsn.database = cx2
resources.doctrine.connections.cx2.dsn.options.option1 = value
resources.doctrine.connections.cx2.dsn.options.option2 = value
 
------------------------------
Set Global Attributes
設定全域共用屬性
------------------------------
resources.doctrine.attributes.auto_accessor_override = 0
resources.doctrine.attributes.auto_free_query_objects = 1
resources.doctrine.attributes.autoload_table_classes = 0
resources.doctrine.attributes.coll_key =
resources.doctrine.attributes.dbname_format = "appname_%s"
resources.doctrine.attributes.export = "all"
resources.doctrine.attributes.idxname_format = "%s_index"
resources.doctrine.attributes.model_loading = "conservative"
resources.doctrine.attributes.portability = "all"
resources.doctrine.attributes.query_cache =
resources.doctrine.attributes.query_limit =
resources.doctrine.attributes.quote_identifier = 0
resources.doctrine.attributes.result_cache =
resources.doctrine.attributes.result_cache_lifespan = 3600
resources.doctrine.attributes.seqname_format = "%s_sequence"
resources.doctrine.attributes.tblname_format = "%s_table"
resources.doctrine.attributes.use_dql_callbacks = 1
resources.doctrine.attributes.use_native_enum = 0
resources.doctrine.attributes.validate = "all"
 
------------------------------
Set Connection Attributes
自定連接資料庫屬性
------------------------------
resources.doctrine.connections.cx1.attributes.auto_accessor_override = 0
resources.doctrine.connections.cx1.attributes.auto_free_query_objects = 1
resources.doctrine.connections.cx1.attributes.autoload_table_classes = 0
resources.doctrine.connections.cx1.attributes.coll_key =
resources.doctrine.connections.cx1.attributes.dbname_format = "appname_%s"
resources.doctrine.connections.cx1.attributes.export = "all"
resources.doctrine.connections.cx1.attributes.idxname_format = "%s_index"
resources.doctrine.connections.cx1.attributes.model_loading = "conservative"
resources.doctrine.connections.cx1.attributes.portability = "all"
resources.doctrine.connections.cx1.attributes.query_cache =
resources.doctrine.connections.cx1.attributes.query_limit =
resources.doctrine.connections.cx1.attributes.quote_identifier = 0
resources.doctrine.connections.cx1.attributes.result_cache =
resources.doctrine.connections.cx1.attributes.result_cache_lifespan = 3600
resources.doctrine.connections.cx1.attributes.seqname_format = "%s_sequence"
resources.doctrine.connections.cx1.attributes.tblname_format = "%s_table"
resources.doctrine.connections.cx1.attributes.use_dql_callbacks = 1
resources.doctrine.connections.cx1.attributes.use_native_enum = 0
resources.doctrine.connections.cx1.attributes.validate = "all"
 
------------------------------
Attach Connection Listeners to Connections
------------------------------
resources.doctrine.connections.cx1.listeners.connection.listener1 = My_Listener1
resources.doctrine.connections.cx1.listeners.connection.listener2 = My_Listener2
resources.doctrine.connections.cx2.listeners.connection.listener2 = My_Listener2
resources.doctrine.connections.cx2.listeners.connection.listener2 = My_Listener2
 
------------------------------
Attach Record Listeners to Connections
------------------------------
resources.doctrine.connections.cx1.listeners.record.listener1 = My_Listener1
resources.doctrine.connections.cx1.listeners.record.listener2 = My_Listener2
resources.doctrine.connections.cx2.listeners.record.listener1 = My_Listener1
resources.doctrine.connections.cx2.listeners.record.listener2 = My_Listener2
 
------------------------------
Add Paths to Registry
自定相關目錄
------------------------------
resources.doctrine.paths.data_fixtures_path = APPLICATION_PATH "/../doctrine/data/fixtures"
resources.doctrine.paths.migrations_path = APPLICATION_PATH "/../doctrine/migrations"
resources.doctrine.paths.models_path = APPLICATION_PATH "/models"
resources.doctrine.paths.yamlschema_path = APPLICATION_PATH "/../doctrine/schema"
resources.doctrine.paths.sql_path = APPLICATION_PATH "/../doctrine/data/sql"
 
9. Class Skeletons
 
ZendX_Doctrine_Application_Resource_Doctrine

此次檔案包含上述整合內容還有ZFDebug Doctrine ORM plugin
點我下載:library

2 thoughts on “Zend Framework 1.11.0 and Doctrine 1.2.3 and Smarty 3.0.4

  1. I am sorry I can’t write in Chinese, and I hope you can understand this.

    I am attempting to follow your examples above, but I am having an issue with Smarty. Here is the errors I am getting:

    Warning: include_once(Smarty.php): failed to open stream: No such file or directory in /usr/local/zend/share/ZendFramework/library/Zend/Loader.php on line 146 Warning: include_once(): Failed opening ‘Smarty.php’ for inclusion (include_path=’/usr/local/zend/apache2/htdocs/groups/application/../library:/usr/local/zend/apache2/htdocs/groups/library:/usr/local/zend/apache2/htdocs/groups/application/models::.:/usr/local/zend/share/ZendFramework/library:/usr/local/zend/share/pear’) in /usr/local/zend/share/ZendFramework/library/Zend/Loader.php on line 146 Fatal error: Class ‘Smarty’ not found in /usr/local/zend/apache2/htdocs/groups/library/ZendX/View/Smarty.php on line 5

    I uncomment out the require_once in ZendX/View/Smarty.php and it moves forward but then it is unable to load the Smarty plugins, specifically Smarty/Internal/Data.php.

    Any ideas?

admin 發表迴響 取消回覆

你的電子郵件位址並不會被公開。 必要欄位標記為 *