zend_Application 的几个作用

当一个 MVC 应用程序被要求加入更多特性的时候,例如:建立数据库,配置你的视图和视图助手,配置你的模板,注册插件,注册动作助手等等,要配置好这个 MVC 应用程序并做好分发的准备,将会增加大量的代码。

另外,你会经常希望重用相同代码来引导你的测试、一个 cronjob(定时工作)、或者一个服务脚本。当只需要简单包括你的引导脚本成为可能的情况下,多数时候这个引导脚本是关于运行环境的初始化设置 - 你不必为了一个 cronjob 创建 MVC,或者为了一个服务脚本只需要提供 DB 层。

Zend_Application 以简化这个过程和提高重用性为目标,方法是通过把引导过程封装进 OOP 规范。

Zend_Application 被分成3个部分:

  • Zend_Application:加载 PHP 环境,包括 include_path 路径和自动加载,以及实例化被请求的引导类。
  • Zend_Application_Bootstrap:为引导类提供接口。Zend_Application_Bootstrap_Bootstrap 为绝大多数的引导需求提供常用功能,包括依赖性检查算法和加载被请求的引导资源。
  • Zend_Application_Resource 为标准引导资源提供了一个接口,这些标准引导资源可以被一个引导实例按需加载;同时 Zend_Application_Resource 还提供了一些默认的资源接口。

开发者通过继承 Zend_Application_Bootstrap_Bootstrap 类或者应用(最低程度的)Zend_Applicatioon_Bootstrap_Bootstrapper 接口,从而为他们的应用程序创建引导类。接入点(例如,public/index.php)将加载 Zend_Application,并传递以下参数来实例化它:

  • 目前的环境
  • 引导选项

引导选项包括了到包含引导类文件的路径和以下可选的内容:

  • 任何需要设置的额外 include_path 路径
  • 任何需要注册的额外自动加载器命名空间
  • 任何需要初始化的 php.ini 设置
  • 引导类的类名(如果类名不是“Bootstrap”)
  • 将被使用的资源的前缀和路径(成对出现)
  • 任何将被使用的资源(通过类名或者短名)
  • 需要另外加载配置文件的路径
  • 额外的配置选项

选项可以是一个数组,一个 Zend_Config 对象,或者到一个配置文件的路径。

引导进程

Zend_Application 职责的第二个领域是执行应用程序的引导程序。引导程序最低程度需要应用 Zend_Application_Bootstrap_Bootstrapper 接口,这个类定义了如下 API:

  1. interface Zend_Application_Bootstrap_Bootstrapper  
  2. {  
  3.     public function __construct($application);  
  4.     public function setOptions(array $oprions);  
  5.     public function getApplication();  
  6.     public function getEnvironment();  
  7.     public function getClassResources();  
  8.     public function getClassResourceNames();  
  9.     public function bootstrap($resource = null);  
  10.     public function run();  
  11. }  

这个 API 允许引导程序接受来自应用程序对象(application object)的环境和设置,把资源对于引导过程的职责报告给该资源,然后引导和运行应用程序。

你可以根据你的要求应用这个接口,继承 Zend_Application_Bootstrap_BootstrapAbstract 或者 Zend_Application_Bootstrap_Bootstrap。

除了这些功能,你还应该熟悉其它大量的相关内容。

资源方法

Zend_Application_Bootstrap_BootstrapAbstract 接口为定义资源方法提供了一个简单约定。任何以一个 _init 前缀名开始的受保护方法将会被视作一个资源方法。

为引导一个单独的资源方法,使用 bootstrap() 方法,然后把资源的名字传递给它。资源的名字将会是资源方法名称去掉 _init 前缀。

为了引导几个资源方法,传递资源名称数组给它。若是想引导全部资源方法,什么参数都不要传递。

看看下面的这个引导类:

  1. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap  
  2. {  
  3.     protected function _initFoo()  
  4.     {  
  5.         // ...  
  6.     }  
  7.   
  8.     protected function _initBar()  
  9.     {  
  10.         // ...  
  11.     }  
  12.   
  13.     protected function _initBaz()  
  14.     {  
  15.         // ...  
  16.     }  
  17. }  

只想引导 _initFoo() 方法的话,这样做:

  1. $bootstrap->bootstrap('foo');  

想引导 _initFoo() 和 _initBar() 方法,这样做:

  1. $bootstrap->bootstrap(array('foo''bar'));  

想引导全部的资源方法,不带任何参数调用 bootstrap():

  1. $bootstrap->bootstrap();  

使用资源插件的引导

为了使你的引导程序更加可重用,我们提供了以下功能:把你的资源加入到资源插件类中。这将允许你只需简单的通过配置就可混用和匹配资源。我们会在稍后提到如何创建资源;在这个部分,我们只会展示如何使用他们。

如果你希望引导程序能够使用资源插件,你将需要应用一个额外的接口,Zend_Application_Bootstrap_ResourceBootstrapper。这个接口定义了一个如下的 API:定位,注册和加载资源插件:

  1. interface Zend_Application_Bootstrap_ResourceBootstrapper  
  2. {  
  3.     public function registerPluginResource($reource$options = null);  
  4.     public function unregisterPluginResource($resource);  
  5.     public function hasPluginResource($resource);  
  6.     public function getPluginResource($resource);  
  7.     public function getPluginResources();  
  8.     public function getPluginResourceNames();  
  9.     public function setPluginLoader(Zend_Loader_PluginLoader_Interface $loader);  
  10.     public function getPluginLoader();  
  11. }  

资源插件基本上提供了创建资源初始器的功能,这些资源初始器可以在应用程序间重复使用。这将允许你保持启动程序的相对干净,同时不必修改引导程序也可以引入新的资源。

Zend_Application_Bootstrap_BootstrapAbstract(同时它的子类 Zend_Application_Bootstrap_Bootstrap)应用了这个接口,它将允许你使用资源插件。

为了使用资源插件,你应该在传递给应用程序对象以及/或引导程序)的选项中指定它们(资源插件)。这些选项可能来自一个配置文件,或者手动传递。选项将会是成对出现的键名和选项值,其中键名表示资源的名字。资源的名字将会是类前缀后面的所有东西。例如,Zend Framework 内置的资源有 Zend_Application_Resource_ 这个前缀,任何这个前缀后面的东西将会是这个资源的名字。请看:

  1. $application = new Zend_Application(APPLICATION_ENV, array(  
  2.     'resources' => array(  
  3.         'FrontController' => array(  
  4.             'controllerDirectory' => APPLICATION_PATH . '/controllers',  
  5.         ),  
  6.     ),  
  7. ));  

这将提示:FrontController 资源将会根据指定的选项被使用。

如果你开始写自己的资源插件,或者利用第三方资源插件,你将需要告诉你的引导程序到哪里找到它们。在内部,引导程序使用 Zend_Loader_PluginLoader,所以你将只需提示它:通用类前缀和路径。

例子,让我们假设你在 APPLICATION_PATH/resources/ 目录下有定制的资源插件,它们都有 My_Resource 这个通用类前缀。你可能把以下的信息传递给应用程序对象:

  1. $application = new Zend_Application(APPLICATION_ENV, array(  
  2.     'pluginPaths' => array(  
  3.         'My_Resource' => APPLICATION_PATH . '/resources/',  
  4.     ),  
  5.     'resources' => array(  
  6.         'FrontController' => array(  
  7.             'controllerDirectory' => APPLICATION_PATH . '/controllers',  
  8.         ),  
  9.     ),  
  10. ));  

你现在应该可以使用那个目录下的资源了。

正如前面提到的资源方法,你使用 bootstrap() 方法来执行资源插件。和资源方法一样,你可以指定一个单独的资源插件,多个插件(通过一个数组),或者全部插件。另外,你也可以混用和匹配执行资源方法和资源插件。

  1. // 执行一个插件:   
  2. $bootstrap->bootstrap('FrontController');  
  3.   
  4. // 执行 N 个插件:  
  5. $bootstrap->bootstrap(array('FrontController''Foo'));  
  6.   
  7. // 执行全部的资源插件和方法:  
  8. $bootstrap->bootstrap();  

资源注册

许多,如果不是全部,你的资源方法或者插件将初始化对象,在大多数情况下,这些对象将会被要求出现在应用程序的其它地方。你如何访问他们(对象)?

Zend_Application_Bootstrap_BootstrapAbstract 为这些对象提供了一个本地注册表。为了在这些注册表上保存你的对象,你只需简单的从你的资源返回它们就行了。

为了最大的灵活性,这个注册表在内部被当作一个“容器”引用;它唯一的要求就是它是一个对象。资源然后被当作属性(这个属性以资源的名字命名)注册。默认的,一个 Zend_Registry 的实例被使用,但是你也可以指定使用任何其它对象。setContainer() 和 getContainer() 方法可以被用来对容器进行操作。getResource($resource) 可以用来捕获容器内的一个指定的资源,hasResource($resource) 用来检查资源是否已经真正被注册。

举例说明,看下面的视图资源:

  1. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap  
  2. {  
  3.     protected function _initView()  
  4.     {  
  5.         $view = new Zend_View();  
  6.         // more initialiazation...  
  7.           
  8.         return $view;  
  9.     }  
  10. }  

你可以通过以下代码检查和/或捕获它:

  1. // 使用 has/getResource() 方法:  
  2. if ($bootstrap->hadResource('view')) {  
  3.     $view = $bootstrap->getResource('view');  
  4. }  
  5.   
  6. // 通过容器:  
  7. $container = $bootstrap->getContainer();  
  8. if (isset($container->view)) {  
  9.     $view = $container->view;  
  10. }  

请注意,注册表和容器都不是全局性的。这意味着为了捕获资源你需要访问引导对象(bootstrap)。Zend_Application_Bootstrap_Bootstrap 为这提供了一些便利:在它的 run() 运行过程中,它把自己当作前端控制器的参数“bootstrap”注册了,这将允许你从路由、分发器、插件和动作控制器捕获它。

举例说明,上述代码中,如果你想从动作控制器内访问视图资源,你可以这样做:

  1. class FooController extends Zend_Controller_Action  
  2. {  
  3.     public function init()  
  4.     {  
  5.         $bootstrap = $this->getInvokeArg('bootstrap');  
  6.         $view = $bootstrap->getResource('view');  
  7.         // ...  
  8.     }  
  9. }  

依赖性检查

为了执行资源方法和插件,确保它们被执行一次并且只有一次,是十分必要的;这些意味着为了引导一个应用程序,执行多次,将会导致资源重载。

同时,一些资源可能依赖于其它资源的执行。为了解决这两个问题,Zend_Application_Bootstrap_BootstrapAbstract 提供了一个简单,有效的依赖性检查机制。

在前面已经说明,全部的资源 —— 无论是方法还是插件 —— 是通过调用引导对象bootstrap($resource) 来启动的,$resource 是资源的名字,一个资源数组,或者,留空指示运行全部的资源。

如果一个资源依赖于其它的资源,它应该在它的内部代码调用 bootstrap() 来确保那个资源(依赖的资源)已经运行。后面对它(bootstrap()?)的调用将被忽略。

在一个资源方法内,这样的调用看起来如下:

  1. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap  
  2. {  
  3.     protected function _initRequest()  
  4.     {  
  5.         // 确保前端控制器已经初始化  
  6.         $this->bootstrap('FrontController');  
  7.       
  8.         // 从引导注册表中检索前端控制器  
  9.         $front = $this->getResource('FrontController');  
  10.   
  11.         $request = new Zend_Controller_Request_Http();  
  12.         $request->setBaseUrl('/foo');  
  13.         $front->setRequest($request);  
  14.   
  15.         // 确保 request 资源已经保存到引导注册表中  
  16.         return $request;  
  17.     }  
  18. }  

资源插件

前面已经提到,创建可重用的引导资源,以及把代码分散到分离的类当中,好的办法是使用资源插件。虽然 Zend Framework 内置了大量的标准资源插件,但是开发者仍有必要自己写的资源插件来封装他们的初始化需求。

资源插件只需要应用 Zend_Application_Resource_Resource 接口,或者,更简单的,继承 Zend_Application_Resource_ResourceAbstract。基本的接口很简单:

  1. interface Zend_Application_Resource_Resource  
  2. {  
  3.     public function __construct($options = null);  
  4.     public function setBootstrap(  
  5.         Zend_Application_Bootstrap_Bootstrap $bootstrap  
  6.     );  
  7.     public function getBootstrap();  
  8.     public function setOptions(array $options);  
  9.     public function getOptions();  
  10.     public function init();  
  11. }  

这个接口简单的定义了,一个资源插件构造函数应该接受的选项,有设置和检索选项的功能,有设置和检索引导对象的功能,以及一个初始化的方法。

举例说明,让我们假设在你的应用程序内有一个通用的初始化视图,有一个通用的 doctype,CSS,和 JavaScript,同时你希望可以通过设置来传递一个基本的文档标题。这样的资源插件看起来是这样的:

  1. class My_Resource_View extends Zend_Application_Resource_ResourceAbstract  
  2. {  
  3.     protected $_view;  
  4.    
  5.     public function init()  
  6.     {  
  7.         // 返回 view 以便 bootstrap 会把它保存到注册表中  
  8.         return $this->getView();  
  9.     }  
  10.    
  11.     public function getView()  
  12.     {  
  13.         if (null === $this->_view) {  
  14.             $options = $this->getOptions();  
  15.             $title   = '';  
  16.             if (array_key_exists('title'$options)) {  
  17.                 $title = $options['title'];  
  18.                 unset($options['title']);  
  19.             }  
  20.    
  21.             $view = new Zend_View($options);  
  22.             $view->doctype('XHTML1_STRICT');  
  23.             $view->headTitle($title);  
  24.             $view->headLink()->appendStylesheet('/css/site.css');  
  25.             $view->headScript()->appendfile('/js/analytics.js');  
  26.    
  27.             $viewRenderer =  
  28.                 Zend_Controller_Action_HelperBroker::getStaticHelper(  
  29.                     'ViewRenderer'  
  30.                 );  
  31.             $viewRenderer->setView($view);  
  32.    
  33.             $this->_view = $view;  
  34.         }  
  35.         return $this->_view;  
  36.     }  
  37. }  
一旦你为这个资源插件注册了前缀路径,你就可以把它用在你的应用程序中了。更妙的是,因为它使用了插件加载器,你将有效的重写 Zend Framework 内置的 View 视图资源插件,确保你的资源插件被使用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值