程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> PHP綜合 >> Zend Framework之Zend_Application組裝應用程序

Zend Framework之Zend_Application組裝應用程序

編輯:PHP綜合
       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)中能夠改善吧。

-
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved