rss· 投稿· 设为首页· 加入收藏· 繁體版
当前位置: 火魔网 » 程序开发 » PHP

Zend Framework之Zend_Application组装应用程序

发布时间:2009-5-21 11:54   作者: admin   信息来源: ZendChina   [我来说两句(275条)]
        Zend Framework1.8的正式发行包中终于把Zend_Application加入其中,这标志着ZF进一步趋向成熟。这两天试着用Zend_Application重构了Bootstrap,觉得虽然还不是很完善,但是也的确大大简化了应用程序的初始化组装过程。

Zend_Application提出的两个关键概念有两个:

1. Bootstrap

对于Bootstrap,我想接触过ZF的人都不会陌生,意即把初始化程序的过程封装,以便管理及修改。在ZF1.8之前,我想大部分人都是这样(或类似这样)写的:
class Bootstrap

    ...

    public function initLoader(){...}

    public function initController(){...}

    public function initDb(){...}

    public function initView(){...}

    public function initLayout(){...}

    public function initSession(){...}

    public function initAuth(){...}

    public function initAcl(){...}

    ...

}
这样通常会导致Bootstrap非常巨大而臃肿,而若以Zend_Application的形式来bootstrap的话只需要创建application实例并编写相关的配置文件(ini)就可以了,至于如何创建我将在下面的内容中详细介绍。

2. Resource

Resource资源的概念实际上可以简单的说成是ZF的组件,例如Zend_Controller, Zend_Db,Zend_View等等,当然它还具有更深层的意思,例如它允许用户自定义对于应用程序的资源,是面向用户的概念。简单的讲就是,它尝试把调用ZF组件的过程封装成程序的资源,然后加以利用。而这样做的好处是显而易见的。例如,在ZF2.0中Zend_Loader::registerAutoload()将被废弃,取而代之以Zend_Loader_Autoloader。如果你的程序中是用functioninitLoader()之类的方法来初始化自动加载的话,那就必须要修改程序了,而应用Zend_Application来帮你完成的话就省去了这些烦人的兼容性问题。

例如Zend_Application_Resource_Db的工作就是实例化Zend_Db对象并设置默认adapter,以下是简化的源代码:
class Zend_Application_Resource_Db extends Zend_Application_Resource_ResourceAbstract

{
    ...

    // Defined by Zend_Application_Resource_Resource

    public function init()

    {
        ...

        $this->_db = Zend_Db::factory($adapter, $this->getParams());

        Zend_Db_Table::setDefaultAdapter($db);

        return $db;
        ...

    }

}
下面,我将尽量详细的介绍运用Zend_Application组装应用程序的过程。

首先是目录结构。

在这里我建立了两个模块分别是front和admin,templates是模版目录,将存放所有的layout及scripts,ZF放在library下,入口index.php放在public下。

让我们先来看index.php的配置:
// Define path to project root

defined('PROJECT_ROOT')

    || define('PROJECT_ROOT',

              realpath(dirname(dirname(__FILE__))));

// Define path to application directory

defined('APPLICATION_PATH')

    || define('APPLICATION_PATH',

              PROJECT_ROOT . '/application');

// Define application environment

defined('APPLICATION_ENV')

    || define('APPLICATION_ENV',

              (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV')

                                         : 'production'));

// Include paths

set_include_path(implode(PATH_SEPARATOR, array(

    PROJECT_ROOT . '/library',

    get_include_path(),

)));

// Zend_Application

require_once 'Zend/Application.php';

// Create application

$application = new Zend_Application(

    APPLICATION_ENV,

    PROJECT_ROOT . '/library/Kbs/Config/Application.ini'

);

umask(0);

// Bootstrap and Run

try {

    $application->bootstrap();

    $application->run();

} catch (Exception $e) {

    // handle exceptions

}
需要解释的是APPLICATION_ENV是预设的系统环境变量,它将用于Application.ini中区分应用程序运行环境,这里预设3个值:development, testing, production,分别表示开发环境,测试环境及实际运行环境。

下面再来看Application.ini的配置:

[production]
autoloadernamespaces.0                                          = "Zend_"
autoloadernamespaces.1                                          = "Kbs_"

phpsettings.error_reporting                                      = 8191
phpsettings.date.timezone                                        = "Asia/Shanghai"
phpSettings.display_startup_errors                          = 0
phpSettings.display_errors                                       = 0
bootstrap.path                                         = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class                                         = "Bootstrap"

resources.FrontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.FrontController.moduleControllerDirectoryName = "controllers"
resources.FrontController.defaultModule = "front"
resources.FrontController.plugins.common = "Kbs_Controller_Plugin_Common"                             
resources.FrontController.noErrorHandler                        = 0
resources.FrontController.throwExceptions                      = 1

resources.view.title                                            = ""
resources.view.encoding                                    = "UTF-8"
resources.view.helperPathPrefix                        = "Kbs_View_Helper_"
resources.view.helperPath                                 = "Kbs/View/Helper/"

resources.view.params.front.basePath              = APPLICATION_PATH "/templates/front/default/"
resources.view.params.front.helperPathPrefix  = "Kbs_View_Helper_Front_"
resources.view.params.front.helperPath           = "Kbs/View/Helper/Front/"
resources.view.params.front.layout                  = "frontlayout"
resources.view.params.front.layoutPath           = APPLICATION_PATH "/templates/front/default/layout"

resources.view.params.admin.basePath = APPLICATION_PATH "/templates/admin/default/"
resources.view.params.admin.helperPathPrefix = "Kbs_View_Helper_Admin_"
resources.view.params.admin.helperPath = "Kbs/View/Helper/Admin/"
resources.view.params.admin.layout  = "adminlayout"
resources.view.params.admin.layoutPath = APPLICATION_PATH "/templates/admin/default/layout"

resources.view.params.pathCss                                 = "/public/css/"
resources.view.params.pathImg                                 = "/public/img/"
resources.view.params.pathJs                                    = "/public/js/"
resources.view.params.doctype                                  = "HTML4_STRICT"
resources.view.params.charset                                   = "utf-8"

resources.layout.layout = "we use resources.view.params.module.layout instead"
resources.layout.layoutPath = "we use resources.view.params.module.layoutPath instead"

resources.db.adapter                                            = "pdo_mysql"
resources.db.params.host                                     = "localhost"
resources.db.params.username                            = "xxx"
resources.db.params.password                            = "xxx"
resources.db.params.dbname                               = "xxx"
resources.db.isDefaultTableAdapter                      = true
resources.db.params.driver_options.1002            = "SET NAMES UTF8;"

resources.locale.default                                        = "en_US"

resources.translate.registry_key                          = "Zend_Translate"
resources.translate.adapter                                 = array
resources.translate.options.scan                          = "directory"
resources.translate.locale                                     = "zh_CN"
resources.translate.data.zh_CN                           = APPLICATION_PATH "/languages/zh_CN.php"
resources.translate.data.en_US                           = APPLICATION_PATH "/languages/en_US.php"
;resources.translate.data                                     = "we use resources.translate.data.locale instead"

resources.session.save_path                               = APPLICATION_PATH "/../repository/session"
resources.session.use_only_cookies                    = 1
resources.session.remember_me_seconds          = 864000

[testing : production]
phpSettings.display_startup_errors                         = 1
phpSettings.display_errors                                      = 1
resources.db.params.username                              = "root"
resources.db.params.password                              = ""
resources.db.params.dbname                                 = "kbs"

[development : production]
phpSettings.display_startup_errors                         = 1
phpSettings.display_errors                                      = 1
resources.db.params.username                               = "root"
resources.db.params.password                               = "root"
resources.db.params.dbname                                  = "kbs"

在这里,testing及development均继承自production。值得注意的是,phpsettings是内置的php运行环境参数设定,当然你也可以用.htaccess或者直接在php.ini中设定好。bootstrap则是初始化应用程序所需的bootstrap类及其路径。resources就是我们所说的资源,目前ZF1.8提供的默认资源总共10个:

Zend_Application_Resource_Db
Zend_Application_Resource_Frontcontroller
Zend_Application_Resource_Layout
Zend_Application_Resource_Locale
Zend_Application_Resource_Modules
Zend_Application_Resource_Navigation
Zend_Application_Resource_Router
Zend_Application_Resource_Session
Zend_Application_Resource_Translate
Zend_Application_Resource_View

相信在未来的版本中会有所增加。

最后是application/Bootstrap.php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap

{
    // To init the view

    protected function _initView()

    {

        $options = $this->getOptions();

        $viewOptions = $options['resources']['view'];

        $view = new Zend_View($viewOptions);

 
        if (!empty($viewOptions['params'])) {

            foreach ($viewOptions['params'] as $key => $value) {

                $view->$key = $value;

            }

        }

        $view->env = $this->getEnvironment();

        $view->bootstrap = $this;

        $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper(

            'ViewRenderer'

        );

        $viewRenderer->setView($view);

        return $view;

    }

    // To init the translate

    protected function _initTranslate()

    {

        $options = $this->getOption('resources');

        $options = $options['translate'];

        if (!isset($options['data'])) {

            throw new Zend_Application_Resource_Exception('No translation source data provided.');

        }

        $adapter = isset($options['adapter']) ? $options['adapter'] : Zend_Translate::AN_ARRAY;

        $session = new Zend_Session_Namespace('locale');

        if ($session->locale) {

            $locale = $session->locale;

        } else {

            $locale  = isset($options['locale']) 

                         ? $options['locale'] 

                         : null;
        }

        $data = '';

        if (isset($options['data'][$locale])) {

            $data = $options['data'][$locale];

        }

        $translateOptions = isset($options['options'])

                                     ? $options['options']

                                     : array();

        $translate = new Zend_Translate(

            $adapter, $data, $locale, $translateOptions

        );

        Zend_Registry::set('Zend_Translate', $translate);

        return $translate;

    }

}
而对于如何为不同模块(module)指定不同的layout的问题,我的解决办法是用controller plugin,也是目前来说比较有效的方法。具体如下:
class Kbs_Controller_Plugin_Common extends Zend_Controller_Plugin_Abstract

    public function routeShutdown(Zend_Controller_Request_Abstract $request)

    {

        $module = $request->getModuleName();
 
        $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper(

            'ViewRenderer'

        );

        $view = $viewRenderer->view;

        $moduleParams = $view->$module;

        $view->addBasePath($moduleParams['basePath']);

        $view->addHelperPath($moduleParams['helperPath'],

                             $moduleParams['helperPathPrefix']);
 
        $layout = $view->layout();

        $layout->setLayoutPath($moduleParams['layoutPath'])

               ->setLayout($moduleParams['layout']);

    }

routeShutdown方法于route之后执行,这为获取module提供了办法,而view和layout所用到的参数都是Application.ini中设置好了的。

以上便是运用Zend_Application配置组装应用程序的基本过程。这里忽略了Zend/Application/Module及其相关内容,这是因为笔者觉得ZF1.8中Zend_Application对于module的支持还不完善,希望在未来的版本(应该是2.0)中能够改善吧。

顶一下
(0)
踩一下
(1)