Zend Framework教程-Application和Bootstrap

时间:2022-01-01 19:34:38

在一个MVC应用程序中,我们需要初始化建立数据库链接,配置视图和视图助手,配置布局,注册相关插件,注册action 助手等等,这些配置和准备工作我们都需要一一完成。有时候可能有一些初始化操作需要,但是在有些情况下这些初始化可能不需要。通过Zend_Application不仅仅可以完成这些操作,而且可以让这些配置和初始化工作更统一有序,重用性更高。
Zend_Application使用可以细分成三种:
  Zend_Application:加载PHP环境,包括include_paths和自动加载,并实例化引导类。
  Zend_Application_Bootstrap:提供引导类的接口。
  Zend_Application_Bootstrap_Bootstrap完成大多数引导需要提供的通用功能,包括依赖性检查和按需加载引导资源。
  Zend_Application_Resource提供资源按需加载功能


开发人员可以根据需要继承Zend_Application_Bootstrap_Bootstrap或实现Zend_Application_Bootstrap_Bootstrapper接口。在入口文件(例如,public/index.php)加载Zend_Application,并根据引导选项和当前环境配置实例化。
引导选项包括指定的引导类文件和引导类路径,选项具体如下:
所需要的include_paths
自动加载功能额外加载注册的命名空间
php.ini初始化设置
指定bootstrap类名,如果不是"Bootstrap"
资源的前缀键值对键表示资源前缀名称
资源的类名或者别名
附加加载的配置文件路径
附加的配置选项
选项可以是一个数组,或者Zend_Config对象,或者是指定位置的配置文件
 
 
引导程序
Zend_Application的第二个功能就是引导应用,Bootstraps 必须实现Zend_Application_Bootstrap_Bootstrapper接口, 具体接口API如下:


interface Zend_Application_Bootstrap_Bootstrapper
{
    public function __construct($application);
    public function setOptions(array $options);
    public function getApplication();
    public function getEnvironment();
    public function getClassResources();
    public function getClassResourceNames();
    public function bootstrap($resource = null);
    public function run();
}
api主要提供了环境配置,获取引导加载的资源,以及引导程序


你可以实现接口或者继承Zend_Application_Bootstrap_BootstrapAbstract,或者Zend_Application_Bootstrap_Bootstrap.


 
资源方法
 
实现Zend_Application_Bootstrap_BootstrapAbstract接口的资源方法必须遵循如下规则. 方法类型是protected,方法的前缀必须是_init will开头.
如果要加载使用一个资源方法,在bootstrap()中添加资源名称即可,资源名称是资源方法去掉_init前缀。
如果要加载使用多个资源方法,可以通过数组指定。
 
例如 bootstrap class:


class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    protected function _initFoo()
    {
        // ...
    }
 
    protected function _initBar()
    {
        // ...
    }
 
    protected function _initBaz()
    {
        // ...
    }
}
只加载使用_initFoo()  :
$bootstrap->bootstrap('foo');
加载使用 _initFoo() and _initBar() :
$bootstrap->bootstrap(array('foo', 'bar'));
加载使用全部资源方法,使用无参的bootstrap():
$bootstrap->bootstrap();








新建first_web项目
root@coder-671T-M:/mydev_src/zend_framework_learn/www# tree first_web/
first_web/
├── application
│   ├── Bootstrap.php
│   ├── configs
│   │   └── application.ini
│   ├── controllers
│   │   ├── ErrorController.php
│   │   └── IndexController.php
│   ├── models
│   └── views
│       ├── helpers
│       └── scripts
│           ├── error
│           │   └── error.phtml
│           └── index
│               └── index.phtml
├── docs
│   └── README.txt
├── library
├── public
│   └── index.php
└── tests
    ├── application
    │   └── controllers
    │       └── IndexControllerTest.php
    ├── bootstrap.php
    ├── library
    └── phpunit.xml


16 directories, 11 files


      较新版本的zend framework引入了Zend_Application和Bootstrap。Zend_Application 提供了一个可重用资源的引导,通用和模块化的引导类和依赖检查。 同时默认负责设置 PHP 环境变量和自动加载功能。
    默认新建项目后,会给出如下的几个文件:
1.项目的Bootstrap
first_web/
├── application
│   ├── Bootstrap.php
具体代码如下:
<?php


class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{




}




2.配置文件
│   ├── configs
│   │   └── application.ini
具体代码如下:
[production]
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
includePaths.library = APPLICATION_PATH "/../library"
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
appnamespace = "Application"
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
resources.frontController.params.displayExceptions = 0


[staging : production]


[testing : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1


[development : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
resources.frontController.params.displayExceptions = 1


3.项目入口文件
├── public
│   └── index.php
<?php


// Define path to application directory
defined('APPLICATION_PATH')
    || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));


// Define application environment
defined('APPLICATION_ENV')
    || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production'));


// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
    realpath(APPLICATION_PATH . '/../library'),
    get_include_path(),
)));


/** Zend_Application */
require_once 'Zend/Application.php';


// Create application, bootstrap, and run
$application = new Zend_Application(
    APPLICATION_ENV,
    APPLICATION_PATH . '/configs/application.ini'
);
$application->bootstrap()
            ->run();
以上代码就是基本的使用Zend_Application方式,完成了环境变量的初始化,加载配置文件,初始化环境,加载模块,完成web应用程序的引导功能。




资源插件
资源插件只需要实现Zend_Application_Resource_Resource,或者,更简单的是,继承Zend_Application_Resource_ResourceAbstract。接口如下:


interface Zend_Application_Resource_Resource
{
    public function __construct($options = null);
    public function setBootstrap(
        Zend_Application_Bootstrap_Bootstrapper $bootstrap
    );
    public function getBootstrap();
    public function setOptions(array $options);
    public function getOptions();
    public function init();
}




例如
class My_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;
    }
}


加载使用资源插件
我了提供资源的重用性,可以将资源方法定义为资源插件。。
为了让bootstrap能够识别资源插件,定义资源插件时,需要实现Zend_Application_Bootstrap_ResourceBootstrapper. 接口定义了查找插件,注册插件和加载插件的api:


interface Zend_Application_Bootstrap_ResourceBootstrapper
{
    public function registerPluginResource($resource, $options = null);
    public function unregisterPluginResource($resource);
    public function hasPluginResource($resource);
    public function getPluginResource($resource);
    public function getPluginResources();
    public function getPluginResourceNames();
    public function setPluginLoader(Zend_Loader_PluginLoader_Interface $loader);
    public function getPluginLoader();
}
采用资源插件,不仅可以让资源可以重复利用,同时让bootstrap更简洁,如果要修改,新增资源也无需修改你的bootstrap。 
通过实现Zend_Application_Bootstrap_BootstrapAbstract (被 Zend_Application_Bootstrap_Bootstrap 继承) ,才可以使用定义的资源插件 


通过将指定的选项传递到application object and/or bootstrap,来注册使用资源插件。这些选项可能会从一个配置文件,或通过手动指定。规则是选项​​必须是键值对,键代表资源名称。资源名称,是资源插件类的类前缀。例如,Zend框架自带的资源类前缀“Zend_Application_Resource_”;任何以下,这都是资源的名称。例如,


$application = new Zend_Application(APPLICATION_ENV, array(
    'resources' => array(
        'FrontController' => array(
            'controllerDirectory' => APPLICATION_PATH . '/controllers',
        ),
    ),
));
"FrontController"资源是个特例。他的选项比较特殊。
无论是使用自己的写的资源插件还是使用第三方的资源插件。你必须保证bootstrap能找到他们,bootstrap 内部通过 Zend_Loader_PluginLoader可以让我们只需要指定资源插件的类前缀,值为资源类的类路径便可以轻松注册资源插件。
例如,如果编写的资源插件存放在APPLICATION_PATH/resources/ 下,类前缀为My_Resource. 可以使用如下方法注册加载:


$application = new Zend_Application(APPLICATION_ENV, array(
    'pluginPaths' => array(
        'My_Resource' => APPLICATION_PATH . '/resources/',
    ),
    'resources' => array(
        'FrontController' => array(
            'controllerDirectory' => APPLICATION_PATH . '/controllers',
        ),
    ),
));
在应用程序中比可以使用指定目录下的资源。
和资源方法类似,通过使用 the bootstrap() 方法可以加载资源插件。加载单一,多个,全部的资源插件的配置方式也类似. 
例如:
// Execute one:
$bootstrap->bootstrap('FrontController');
 
// Execute several:
$bootstrap->bootstrap(array('FrontController', 'Foo'));
 
// Execute all resource methods and plugins:
$bootstrap->bootstrap();




资源注册表
为了避免资源的重复注册,导致不必要的浪费Zend_Application_Bootstrap_BootstrapAbstract 提供了一个本地注册表对象存储这些资源对象.当你想要存放一个资源的时候,只需要在方法中返回这个资源即可。


为了灵活性,注册表是作为一个内部“容器”存在的。只要是对象都可以存入到容器中。资源名称对应为容器的属性。默认情况下,可以通过Zend_Registry获取实例使用,也可以自定义其他对象。 setContainer() and getContainer() 方法可用于操纵容器本身。getResource($resource) 可用于获取一个指定资源。hasResource($resource) 可以检查资源是否已经注册存在


例如,注册一个view资源:


class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    protected function _initView()
    {
        $view = new Zend_View();
        // more initialization...
 
        return $view;
    }
}
资源的相关操作:


// Using the has/getResource() pair:
if ($bootstrap->hasResource('view')) {
    $view = $bootstrap->getResource('view');
}
 
// Via the container:
$container = $bootstrap->getContainer();
if (isset($container->view)) {
    $view = $container->view;
}


请注意:注册表容器是不是全局的。这意味着你需要通过访问的bootstrap来获取资源。 Zend_Application_Bootstrap_Bootstrap提供了 run() , 执行了 run() 之后,它会注册为前端控制器参数的“bootstrap”,通过他可以获取路由器,分发器,插件和动作控制器。


具体使用方法:


class FooController extends Zend_Controller_Action
{
    public function init()
    {
        $bootstrap = $this->getInvokeArg('bootstrap');
        $view = $bootstrap->getResource('view');
        // ...
    }
}


为了防止重复注册加载资源方法和插件或一些资源可能依赖于其他资源。为了解决这两个问题,Zend_Application_Bootstrap_BootstrapAbstract提供了一个简单的依赖性跟踪机制。
如前所述,所有的资源 - 无论是方法或插件 - 是通过 bootstrap($resource)加载运行的,其中 $resource是资源的名称,或者资源名称数组,或者为空,为空表示加载运行所有资源。
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    protected function _initRequest()
    {
        // Ensure the front controller is initialized
        $this->bootstrap('FrontController');
 
        // Retrieve the front controller from the bootstrap registry
        $front = $this->getResource('FrontController');
 
        $request = new Zend_Controller_Request_Http();
        $request->setBaseUrl('/foo');
        $front->setRequest($request);
 
        // Ensure the request is stored in the bootstrap registry
        return $request;
    }
}