ZendFramework資源載入過程分析

來源:互聯網
上載者:User

本篇文章主要是在分析ZendFramework1.11版對自訂的Resource的載入過程,也是個人在分析過程中遇到問題的整理
1、為了瞭解這個過程我們先從網上已有的Resource的開發執行個體(正確的樣本)配置產品
在library目錄下添加resource目錄作為個人開發resource外掛程式的路徑;
增加一個View外掛程式,替換掉現有的bootstrap.php下面的initView方法
<?php
class Resource_View extends Zend_Application_Resource_ResourceAbstract
{
    protected $_view;
 
    public function init()
    {
        // Return view so bootstrap will store it in the registry
        return $this->getView();
    }
 
    public function getView()
    {
        if (null === $this->_view) {
            $options = $this->getOptions();
            $title   = '';
            if (array_key_exists('title', $options)) {
                $title = $options['title'];
                unset($options['title']);
            }
 
            $view = new Zend_View($options);
            $view->doctype('XHTML1_STRICT');
            $view->headTitle($title);
            $view->headLink()->appendStylesheet('/css/site.css');
            $view->headScript()->appendfile('/js/analytics.js');
 
            $viewRenderer =
                Zend_Controller_Action_HelperBroker::getStaticHelper(
                    'ViewRenderer'
                );
            $viewRenderer->setView($view);
 
            $this->_view = $view;
          }
          return $this->_view; }
}
這樣我們就有了一個resource了,下一步需要配置Zend使其載入
個人喜歡使用php數組來配置Zend(ZF2.0也使用了數組 : ) )
<?php
//product
$phpSettings['display_startup_errors'] = 0;
$phpSettings['display_errors'] = 0;
$bootstrap['path'] = APPLICATION_PATH . "/Bootstrap.php";
$bootstrap['class'] = "Bootstrap";
$resources['frontController']['controllerDirectory'] = APPLICATION_PATH . "/controllers";
$resources['frontController']['params']['displayExceptions'] = 0;
$resources['view'] = true;
$autoloaderNamespaces = "Resource_";
$pluginpaths['Resource'] = "resource";

$configs['autoloaderNamespaces'][] = $autoloaderNamespaces;
$configs['pluginpaths'] = $pluginpaths;
$configs['phpSettings'] = $phpSettings;
$configs['includePaths'] = $includePaths;
$configs['bootstrap'] = $bootstrap;
$configs['appnamespace'] = "Application";
$configs['resources'] = $resources;
$configs['path'] = APPLICATION_PATH . "/views/scripts";
這個裡面增加的有resource數組中的View,表示增加我們的自訂的View資源;
autoloaderNamespaces增加資源的命名空間,涉及到ZF1的檔案自動載入問題;
pluginpaths增加自訂資源的外掛程式路徑,也就是在include_path下面的路徑(個人感覺有些多餘)

2、ZF1初始化和資源載入
主要在index.php入口檔案中的application的載入過程實現這個部分,我們來看看這個過程
$application = new Zend_Application(
APPLICATION_ENV,
$configs);
$application->bootstrap()
            ->run();
Zend_Application執行個體化包含類載入器的執行個體化,設定配置參數。
require_once 'Zend/Loader/Autoloader.php';
$this->_autoloader = Zend_Loader_Autoloader::getInstance();
設定參數實際上就是協助開發人員自動化佈建phpsetting,includepath,自動載入命名空間(autoloadernamespaces),執行個體化bootstrap類(這個執行個體化過程載入了Frontcontroller資源,載入在Zend_Application_Bootstrap_Bootstrap的類構造方法中),具體看setOptions方法。
補充:pluginpaths這個參數會在Zend_Application_Bootstrap_BootstrapAbstract的setOptions這個方法中被添加為外掛程式載入器的路徑參數
自動載入命名空間(autoloadernamespaces):設定了自動載入器可以載入的類首碼部分,如果不設定自訂的類命名空間,就會無法載入相應類,這個設定可以在設定檔中做(application.php|application.ini),也可以手動設定通過$loader->registerNamespace($namespace)來實現,具體可以看Zend_Loader_Autoloader.php檔案。
$application的bootstrap()方法主要載入Resource,包括架構必須的Resource和自訂的,載入的過程在Zend_Application_Bootstrap_BootstrapAbstract類的_bootstrap方法中實現
protected function _bootstrap($resource = null)
    {
        if (null === $resource) {
            foreach ($this->getClassResourceNames() as $resource) {
                $this->_executeResource($resource);
            }

            foreach ($this->getPluginResourceNames() as $resource) {
                $this->_executeResource($resource);
            }
        } elseif (is_string($resource)) {
            $this->_executeResource($resource);
        } elseif (is_array($resource)) {
            foreach ($resource as $r) {
                $this->_executeResource($r);
            }
        } else {
            throw new Zend_Application_Bootstrap_Exception('Invalid argument passed to ' . __METHOD__);
        }
    }
主要有兩個部分的處理
1、載入類定義的資源,基本都是個人在開發中通過_init方法定義的資源初始化行為,這個過程通過getClassResourceNames方法擷取類資源,通過ReflectionObject或get_class_methods方法實作類別方法名的擷取
例如:在Bootstrap.php中定義一個如下方法,就可以自動被執行並初始化Request資源
protected function _initRequest()
{
    // Ensure front controller instance is present, and fetch it
    $this->bootstrap('FrontController');
    $front = $this->getResource('FrontController');
 
    // Initialize the request object
    $request = new Zend_Controller_Request_Http();
    $request->setBaseUrl('/foo');
    // Add it to the front controller
    $front->setRequest($request);
 
    // Bootstrap will store this value in the 'request' key of its container
    return $request;
 }
2、載入自訂的類資源,載入配置中設定的資源,也可以載入bootstrap方法給的參數資源(由於資源存在多處設定載入的問題,_executeResource中增加了資源的是否載入的判斷),由Zend_Application_Bootstrap_BootstrapAbstract的_bootstrap方法執行載入
protected function _bootstrap($resource = null)
    {
        if (null === $resource) {
            foreach ($this->getClassResourceNames() as $resource) {
                $this->_executeResource($resource);
            }

            foreach ($this->getPluginResourceNames() as $resource) {
                $this->_executeResource($resource);
            }
        } elseif (is_string($resource)) {
            $this->_executeResource($resource);
        } elseif (is_array($resource)) {
            foreach ($resource as $r) {
                $this->_executeResource($r);
            }
        } else {
            throw new Zend_Application_Bootstrap_Exception('Invalid argument passed to ' . __METHOD__);
        }
    }
載入的過程在_loadPluginResource中執行,Zend_Loader_PluginLoader的load會根據resource的名稱驗證並返回類名,在Zend_Application_Bootstrap_BootstrapAbstract的_loadPluginResource中執行個體化並註冊資源外掛程式
protected function _loadPluginResource($resource, $options)
    {
        $options   = (array) $options;
        $options['bootstrap'] = $this;
        $className = $this->getPluginLoader()->load(strtolower($resource), false);

        if (!$className) {
            return false;
        }

        $instance = new $className($options);

       unset($this->_pluginResources[$resource]);
        if (isset($instance->_explicitType)) {
            $resource = $instance->_explicitType;
        }
        $resource = strtolower($resource);
        $this->_pluginResources[$resource] = $instance;

        return $resource;
    }

接下來就是在_executeResource中執行資源的init方法,然後把init的返回結果儲存在_container容器中(就是一個Zend_Registry執行個體),資源的載入和緩衝也就OK了。

參考:

http://blog.madarco.net/327/how-to-make-your-own-zend-framework-resource-plugin/

http://framework.zend.com/manual/1.11/en/zend.application.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.