Zend Framework(ZF1/ZF2 早期)通过 Zend_Application 统一引导流程:环境初始化、自动加载、配置加载、资源插件按需实例化、依赖解析。本文详解核心组件交互、资源方法/插件开发、Bootstrap 扩展点、容器注册表用法。
Zend_Application
├─ 加载 PHP 环境(include_path、autoloader、php.ini 设置)
├─ 实例化 Bootstrap 类(默认 Bootstrap)
└─ 执行 bootstrap()->run()
Zend_Application_Bootstrap_Bootstrap (抽象基类)
├─ 资源方法:_initXxx() 约定
├─ 资源插件:pluginResources.* 配置
├─ 依赖跟踪:bootstrap($resource) 递归解析
└─ 注册表:getResource()/hasResource() 存取已初始化资源
Zend_Application_Resource_ResourceAbstract
└─ 资源插件基类:init() 返回资源实例,自动存入注册表
my-project/
├── application/
│ ├── Bootstrap.php
│ ├── configs/
│ │ └── application.ini
│ ├── controllers/
│ ├── models/
│ └── views/
├── library/
├── public/
│ └── index.php
└── tests/
<?php
defined('APPLICATION_PATH') || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
defined('APPLICATION_ENV') || define('APPLICATION_ENV', getenv('APPLICATION_ENV') ?: 'production');
set_include_path(implode(PATH_SEPARATOR, [
realpath(APPLICATION_PATH . '/../library'),
get_include_path(),
]));
require_once 'Zend/Application.php';
$app = new Zend_Application(
APPLICATION_ENV,
APPLICATION_PATH . '/configs/application.ini'
);
$app->bootstrap()->run();
[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
resources.db.adapter = "PDO_MYSQL"
resources.db.params.host = "localhost"
resources.db.params.dbname = "myapp"
resources.db.params.username = "user"
resources.db.params.password = "pass"
resources.db.params.charset = "utf8"
resources.view.encoding = "UTF-8"
resources.layout.layoutPath = APPLICATION_PATH "/views/layouts"
[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
resources.db.params.dbname = "myapp_test"
<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
// 1. 资源方法:_init + 驼峰名
protected function _initView()
{
$view = new Zend_View();
$view->setEncoding('UTF-8');
$view->doctype('HTML5');
$view->headTitle('My App')
->headLink()->appendStylesheet('/css/app.css')
->headScript()->appendFile('/js/app.js');
// 返回值自动存入注册表,键为 'view'
return $view;
}
protected function _initDb()
{
// 依赖前置资源:确保配置已加载
$this->bootstrap('FrontController'); // 触发 _initFrontController
$db = $this->getPluginResource('db')->init(); // 直接获取 DB 资源
Zend_Registry::set('db', $db);
return $db;
}
// 2. 自定义资源方法:注册服务
protected function _initServices()
{
$serviceManager = new Zend_ServiceManager();
$serviceManager->setInvokableClass('user_service', 'Application\Service\UserService');
return $serviceManager;
}
}
<?php
// library/My/Resource/View.php
class My_Resource_View extends Zend_Application_Resource_ResourceAbstract
{
public function init()
{
$options = $this->getOptions();
$view = new Zend_View($options);
$view->doctype('HTML5');
$view->headTitle($options['title'] ?? 'Default Title');
// 配置 ViewRenderer 助手
$renderer = Zend_Controller_Action_HelperBroker::getStaticHelper('ViewRenderer');
$renderer->setView($view);
return $view; // 自动注册到 Bootstrap 注册表
}
}
<?php
// 在 Bootstrap.php 或入口文件
$app = new Zend_Application(APPLICATION_ENV, [
'pluginPaths' => [
'My_Resource' => APPLICATION_PATH . '/resources/', // 对应 library/My/Resource/
],
'resources' => [
'view' => [ // 键对应插件类名后缀 View
'title' => 'My Custom Title',
],
'frontController' => [
'controllerDirectory' => APPLICATION_PATH . '/controllers',
],
],
]);
<?php
// 在 Controller 中获取 Bootstrap 注册的资源
class IndexController extends Zend_Controller_Action
{
public function init()
{
$bootstrap = $this->getInvokeArg('bootstrap'); // 前端控制器参数中注入
// 方式 1:has/getResource
if ($bootstrap->hasResource('view')) {
$view = $bootstrap->getResource('view');
}
// 方式 2:容器访问
$container = $bootstrap->getContainer();
$view = $container->view ?? null;
}
}
<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initRequest()
{
// 1. 声明依赖:确保 FrontController 已初始化
$this->bootstrap('FrontController');
// 2. 从注册表获取依赖资源
$front = $this->getResource('FrontController');
// 3. 业务逻辑:设置自定义 Request
$request = new Zend_Controller_Request_Http();
$request->setBaseUrl('/myapp');
$front->setRequest($request);
// 4. 返回资源实例,存入注册表
return $request;
}
}
bootstrap($resource) 会递归解析依赖,已初始化的资源直接返回,避免重复执行。
<?php
$loader = new Zend_Loader_PluginLoader([
'My_Resource_' => 'My/Resource/', // 前缀 -> 路径映射
'Zend_Application_Resource_' => 'Zend/Application/Resource/',
]);
// 加载 View 资源插件
$class = $loader->load('View'); // 返回 'My_Resource_View' 或 'Zend_Application_Resource_View'
$plugin = new $class($options);
$resource = $plugin->init();
$app->run() 执行后,Bootstrap 实例被注册为前端控制器参数 bootstrap,可在以下位置访问:
$this->getInvokeArg('bootstrap')$front->getParam('bootstrap')$this->view->bootstrap() (需自定义助手)_ENV 继承,开发/测试/生产仅差异配置。_initXxx 仅初始化一个资源,复杂逻辑拆分到服务类。pluginPaths 注册。$this->bootstrap('dependency') 让依赖图可视化,避免隐式顺序耦合。Zend_Registry 滥用造成隐式依赖。| ZF1 | ZF2 / Laminas |
|---|---|
| Zend_Application | Zend\Mvc\Application + ServiceManager |
| Bootstrap 资源方法 | Module.php onBootstrap() + ServiceManager 工厂 |
| 资源插件 | ServiceManager 抽象工厂/初始化器 |
| application.ini | config/autoload/*.global.php + *.local.php |
| Zend_Registry | ServiceManager 获取服务 |
| Zend_Loader_PluginLoader | Composer PSR-4 + ServiceManager 插件管理器 |