ce 'Zend/Application.php';
$application = new Zend_Application(
APPLICATION_ENV,
array(
'resources' => array(
'FrontController' => array(
'controllerDirectory' => APPLICATION_PATH . '/controllers',
),
),
)
);
// 加载资源并运行程序
$application->bootstrap();
$application->run();
而通过 Zend_Application_Resource_ResourceAbstract 虚拟类,我们可以很方便的注册自己的资源,然后通过配置文件 (如 Application.ini) 安插进各自的 Bootstrap 过程中。而同时我们可以通过 Zend_Application_Bootstrap_Bootstrap::bootstrap($resource) 方法来动态载入所需资源 (resource) 。
例如我要注册一个自定义的视图 (View) 资源 :
// 自定义 view 资源
class Kbs_Application_Resource_View extends Zend_Application_Resource_ResourceAbstract
{
protected $_view;
// 初始化 view
// @return Zend_View $view
public function init()
{
if (null === $this->_view) {
$options = $this->getOptions();
$view = new Zend_View($options);
......
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper(
'ViewRenderer'
);
$viewRenderer->setView($view);
$this->_view = $view;
}
return $this->_view;
}
}
接着是配置 :
$application = new Zend_Application(APPLICATION_ENV, array(
// 自定义资源的路径及其前缀
'pluginPaths' => array(
'Kbs_Application_Resource' => 'Kbs/Application/Resource/',
),
'resources' => array(
'FrontController' => array(...),
......
// View 资源
'View' => array('title' => 'my application'),
),
));
当然也可以写在配置文件中,例如 :
// Application.ini
pluginPaths.Kbs_Application_Resource = APPLICATION_PATH "/../library/Kbs/Application/Resource/"
resources.view.title = "my application"
resources.view.encoding = "UTF-8"
然后给出配置文件路径 :
$application = new Zend_Application(
APPLICATION_ENV,
PROJECT_ROOT . '/Config/Application.ini'
));
经过以上的预习,我们大致了解了一下 Zend_Application 及 Zend_Application_Resource 的情况。接下来让我们正式进入主题 : 如何用 Zend_Application 实现应用程序的模块化及模板化设计。
Zend Framework 在基于 MVC 结构之上,提供了一套完整的模块设计 (Modular Design) 方案,可以说 Zend Framework 中的 MVC 是建立在模块之下的,每个模块都可以拥有自己的完整的 MVC 结构。
但是在 Zend Framework 中为不同模块设置不同模板,甚至为同一模块设置多个模板确不是那么容易的,需要一定的配置和技巧。
首先,我们创建应用程序目录结构如下 :
在 application 目录下我们设有 modules 及 templates 两个目录,其中各都有 admin 及 front 两个模块。modules 中的各个模块的 controllers 文件夹是存放所有控制器的地方,如 IndexController 等。templates 中的各个模块文件夹则存放所有的模板,如上图,模块 front 中存放了名为 default 和 oceanStyle 两种模板。
我们将拓展资源放在 library/Kbs/Application/Resource/ 目录下 :
再来是完整的配置文件 :
; Application.ini
[production]
;=========== 库文件路径
;includePaths.library = APPLICATION_PATH "/../library/"
;=========== 类自动加载的前缀
autoloadernamespaces.0 = "Zend_"
autoloadernamespaces.1 = "ZendX_"
autoloadernamespaces.2 = "Kbs_"
;=========== php ini 配置
phpsettings.date.timezone = "Asia/Shanghai"
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
phpsettings.error_reporting = 8191
;=========== bootstrap 类的路径及类名
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
;=========== 自定义资源的路径及其前缀
pluginPaths.Kbs_Application_Resource = APPLICATION_PATH "/../library/Kbs/Application/Resource/"
;=========== front controller 配置
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules/"
resources.frontController.moduleControllerDirectoryName = "controllers"
resources.frontController.defaultModule = "front"
resources.frontController.plugins.common = "Kbs_Controller_Plugin_Common"
resources.frontController.noErrorHandler = 0
resources.frontController.throwExceptions = 1
;=========== layout 布局,实际上我们交由 view 来配置
resources.layout.layout = "we use resources.view.params.module.layout instead"
resources.layout.layoutPath = "we use resources.view.params.module.layoutPath instead"
;=========== view 配置
resources.view.title = ""
resources.view.encoding = "UTF-8"
resources.view.helperPathPrefix = "Kbs_View_Helper_"
resources.view.helperPath = "Kbs/View/Helper/"
;=========== front 和 admin 模块的 view 参数,包括 scripts 文件路径及前缀,layout 路径及名称
resources.view.params.front.basePath = APPLICATION_PATH "/templates/front/default/"
resources.view.params.front.helperPathPrefix = "Kbs_View_Helper_Front_"
resources.view.params.front.helperPath = "Kbs/View/Helper/Front/"
resources.view.params.front.layout = "frontlayout"
resources.view.params.front.layoutPath = APPLICATION_PATH "/templates/front/default/layout/"
resources.view.params.admin.basePath = APPLICATION_PATH "/templates/admin/default/"
resources.view.params.admin.helperPathPrefix = "Kbs_View_Helper_Admin_"
resources.view.params.admin.helperPath = "Kbs/View/Helper/Admin/"
resources.view.params.admin.layout = "adminlayout"
resources.view.params.admin.layoutPath = APPLICATION_PATH "/templates/admin/default/layout/"
;=========== view 的其它参数
resources.view.params.pathCss = "/public/css/"
resources.view.params.pathImg = "/public/img/"
resources.view.params.pathJs = "/public/js/"
resources.view.params.doctype = "HTML4_STRICT"
resources.view.params.charset = "utf-8"
;=========== 数据库配置
resources.db.adapter = "pdo_mysql"
resources.db.params.host = "localhost"
resources.db.params.username = "xxx"
resources.db.params.password = "xxx"
resources.db.params.dbname = "xxx"
resources.db.isDefaultTableAdapter = true
resources.db.params.driver_options.1002 = "SET NAMES UTF8;"
;=========== 翻译配置
resources.translate.registry_key = "Zend_Translate"
resources.translate.adapter = "array"
resources.translate.options.scan = "directory"
resources.translate.data.directory = APPLICATION_PATH "/languages/"
resources.translate.data.fileExt = ".php"
;=========== locale
resources.locale = true
[testing : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
phpsettings.error_reporting = 8191
resources.db.params.username = "xxx"
resources.db.params.password = "xxx"
resources.db.params.dbname = "xxx"
[development : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
phpsettings.error_reporting = 8191
resources.db.params.username = "xxx"
resources.db.params.password = "xxx"
resources.db.params.dbname = "xxx"
在这里,testing 及 development 均继承自 production 环境。值得注意的是,phpsettings.* 是内置的 php 运行环境参数设定, 当然你也可以用 .htaccess 或者直接在 php.ini 中设定好。bootstrap.* 则是初始化应用程序所需的 bootstrap 类及其路径。而 resources.* 就是我们所说的资源。
以上仅为个人的配置,不一定适合每个应用,具体还要按自己需要修改。
接下来就是 index.php 入口 :
// 项目根目录
defined('PROJECT_ROOT')
|| define('PROJECT_ROOT',
realpath(dirname(dirname(__FILE__))));
// 定义到 application 的路径
defined('APPLICATION_PATH')
|| define('APPLICATION_PATH',
PROJECT_ROOT . '/application');
// 定义开发环境
defined('APPLICATION_ENV')
|| define('APPLICATION_ENV',
(getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV')
: 'production'));
// Include paths
set_include_path(implode(PATH_SEPARATOR, array(
PROJECT_ROOT . '/library'
)));
// Zend_Application
require_once 'Zend/Application.php';
// Create application
$application = new Zend_Application(
APPLICATION_ENV,
PROJECT_ROOT . '/library/Kbs/Config/Application.ini'
);
// 开发环境下打开自动加载警告
if ('production' !== APPLICATION_ENV) {
$application->getAutoloader()->suppressNotFoundWarnings(false);
}
// 我们仅加载 frontController 资源
$application->getBootstrap()->bootstrap('FrontController');
$application->run();
需要解释的是 APPLICATION_ENV 是预设的系统环境变量,它将用于 Application.ini 中区分应用程序运行环境,这里预设3个值:development, testing, production,分别表示开发环境,测试环境及实际运行环境。
注意我们在最开始仅仅载入了 frontController 这个资源,这是为了将初始化资源降到最低限度。我们将把其它资源部分地交由 Kbs_Controller_Plugin_Common 插件来按需分配,而余下部分则在需要时再通过 Zend_Application_Bootstrap_Bootstrap::bootstrap($resource) 按需加载。
我们使用 plugin resource 而不是使用在 bootstrap 中重载资源(e.g. Bootstrap::_initView)的方法来进行资源管理,这样的好处是我们的 Bootstrap 类将非常简洁 :
// Kbs/Application/Bootstrap.php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
// 我们不需要在这里重载任何资源
}
现在我们需要让程序 frontController 知道模板 (template) 的位置,为此我们不得不使用动作插件 (action plugin),这个我们已经在前面 Application.ini 中定义好了 :
// 自定义拓展插件,名为 common
resources.FrontController.plugins.common = "Kbs_Controller_Plugin_Common"
// 自定义应用程序插件 Kbs_Controller_Plugin_Common 类
require_once('Zend/Controller/Plugin/Abstract.php');
class Kbs_Controller_Plugin_Common extends Zend_Controller_Plugin_Abstract
{
// route 结束时
public function routeShutdown(Zend_Controller_Request_Abstract $request)
{
// 获取模块名,如 admin,front 等
$module = $request->getModuleName();
// bootstrap 类
$bootstrap = Zend_Controller_Front::getInstance()->getParam('bootstrap');
// 加载 view
$bootstrap->bootstrap('View');
$view = $bootstrap->getResource('View');
$moduleParams = $view->$module;
// 配置 view
$view->addBasePath($moduleParams['basePath'])
->addHelperPath($moduleParams['helperPath'],
$moduleParams['helperPathPrefix']);
// 加载 layout 并配置
$bootstrap->bootstrap('Layout');
$layout = $bootstrap->getResource('Layout');
$layout->setLayoutPath($moduleParams['layoutPath'])
->setLayout($moduleParams['layout']);
}
}
Plugin 是我目前所能想到的最好的解决方案,因为我们将在 routeShutdown 路由结束时很方便的取得 module 模块名,从而根据预先在 Application.ini 里面设定的配置信息,来获取相应的模板信息。
资源 Kbs_Application_Resource_View 定义如下 :
// 拓展资源 (plugin resource) view
class Kbs_Application_Resource_View extends Zend_Application_Resource_ResourceAbstract
{
protected $_view;
// 初始化 view
public function init()
{
if (null === $this->_view) {
// 获取从 Application.ini中 的配置
$options = $this->getOptions();
$view = new Zend_View($options);
if (!emptyempty($options['params'])) {
foreach ($options['params'] as $key => $value) {
$view->$key = $value;
}
}
// viewRenderer 动作助手
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper(
'ViewRenderer'
);
// 保存配置好的视图对象
$viewRenderer->setView($view);
$this->_view = $view;
}
return $this->_view;
}
}
到此,我们已经基本上完成了所有工作。接下来就是完成 layout 及 scripts 了,当然这不一定是程序员做的事了,大可交给专业设计人员。
上例中,只要把
resources.view.params.front.basePath = APPLICATION_PATH "/templates/front/default/"
resources.view.params.front.layoutPath = APPLICATION_PATH "/templates/front/default/layout"
换成
resources.view.params.front.basePath = APPLICATION_PATH "/templates/front/oceanStyle/"
resources.view.params.front.layoutPath = APPLICATION_PATH "/templates/front/oceanStyle/layout"
就能够把模板从 default 切换成 oceanStyle 。
以上便是如何用 Zend_Application 配置及组装应用程序,并完成多模块及多模板的基本过程。这里我忽略了 Zend/Application/Module 及其相关内容,因为据内部消息称,在版本1.9及2.0之前,这部分内容还会有较大修正和改善,所以在这里就不详细说明了 .