zendFramework引导过程通过Application组件完成,由于是对老版本的兼容扩展,其实现起来感觉没有yii那样优雅,它把类库当做资源,而原来那些类库又没有统一的接口,因此又需要新写资源类来间接配置和获取相应的资源。
Zend_Application
zendFramework配置的加载通过入口文件实例Zend_Application来完成,构造方法通过初始化配置后,通过setOptions方法来加载应用的配置。在配置中主要有phpsettings、includepaths、autoloadernamespaces、autoloaderzfpath、bootstrap、appnamespace、resources等。
public function setOptions(array $options) { if (!empty($options['config'])) { if (is_array($options['config'])) { $_options = array(); foreach ($options['config'] as $tmp) { $_options = $this->mergeOptions($_options, $this->_loadConfig($tmp)); } $options = $this->mergeOptions($_options, $options); } else { $options = $this->mergeOptions($this->_loadConfig($options['config']), $options); } } $this->_options = $options; $options = array_change_key_case($options, CASE_LOWER); $this->_optionKeys = array_keys($options); if (!empty($options['phpsettings'])) { $this->setPhpSettings($options['phpsettings']); } if (!empty($options['includepaths'])) { $this->setIncludePaths($options['includepaths']); } if (!empty($options['autoloadernamespaces'])) { $this->setAutoloaderNamespaces($options['autoloadernamespaces']); } if (!empty($options['autoloaderzfpath'])) { $autoloader = $this->getAutoloader(); if (method_exists($autoloader, 'setZfPath')) { $zfPath = $options['autoloaderzfpath']; $zfVersion = !empty($options['autoloaderzfversion']) ? $options['autoloaderzfversion'] : 'latest'; $autoloader->setZfPath($zfPath, $zfVersion); } } if (!empty($options['bootstrap'])) { $bootstrap = $options['bootstrap']; if (is_string($bootstrap)) { $this->setBootstrap($bootstrap); } elseif (is_array($bootstrap)) { if (empty($bootstrap['path'])) { throw new Zend_Application_Exception('No bootstrap path provided'); } $path = $bootstrap['path']; $class = null; if (!empty($bootstrap['class'])) { $class = $bootstrap['class']; } $this->setBootstrap($path, $class); } else { throw new Zend_Application_Exception('Invalid bootstrap information provided'); } } return $this; }Bootstrap
在zf应用中,把框架中类库的看做资源,配置中以resources开头的都是资源相关配置,如resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"配置控制器所在的目录。Zend_Application通过配置实例化Bootstrap来配置资源。
public function setOptions(array $options) { $this->_options = $this->mergeOptions($this->_options, $options); $options = array_change_key_case($options, CASE_LOWER); $this->_optionKeys = array_merge($this->_optionKeys, array_keys($options)); $methods = get_class_methods($this); foreach ($methods as $key => $method) { $methods[$key] = strtolower($method); } if (array_key_exists('pluginpaths', $options)) { $pluginLoader = $this->getPluginLoader(); foreach ($options['pluginpaths'] as $prefix => $path) { $pluginLoader->addPrefixPath($prefix, $path); } unset($options['pluginpaths']); } foreach ($options as $key => $value) { $method = 'set' . strtolower($key); if (in_array($method, $methods)) { $this->$method($value); } elseif ('resources' == $key) { foreach ($value as $resource => $resourceOptions) { $this->registerPluginResource($resource, $resourceOptions); } } } return $this; }配置加载好后,需要启动支持程序运行的,在_bootstrap()首先通过中getClassResourceNames()将获捕获导类中以_init开头的方法,这些方法是通过在引导类内部配置相关资源,然后获取配置中的资源并执行引导,在执行引导的时候会把资源注册在一个全局容器中,通过getResource($resource)方法可以获取容器中的资源。
/** * 获取内部和外部配置资源并执行 */ 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__); } } /** * Execute a resource 执行资源并注册全局资源实例 */ protected function _executeResource($resource) { $resourceName = strtolower($resource); if (in_array($resourceName, $this->_run)) { return; } if (isset($this->_started[$resourceName]) && $this->_started[$resourceName]) { throw new Zend_Application_Bootstrap_Exception('Circular resource dependency detected'); } $classResources = $this->getClassResources(); if (array_key_exists($resourceName, $classResources)) { $this->_started[$resourceName] = true; $method = $classResources[$resourceName]; $return = $this->$method(); unset($this->_started[$resourceName]); $this->_markRun($resourceName); if (null !== $return) { $this->getContainer()->{$resourceName} = $return; } return; } if ($this->hasPluginResource($resource)) { $this->_started[$resourceName] = true; $plugin = $this->getPluginResource($resource); $return = $plugin->init(); unset($this->_started[$resourceName]); $this->_markRun($resourceName); if (null !== $return) { $this->getContainer()->{$resourceName} = $return; } return; } throw new Zend_Application_Bootstrap_Exception('Resource matching "' . $resource . '" not found'); }
引导程序加载完成后,通过run()方法,获取前端控制器,然后前端控制器执行对请求的应答过程。