Zend Framework 整合 Smarty 模板引擎(ZF Study)
<文章大部分内容取自《PHP Web 2.0 》这本书>,最近在学习这本书 ^ ^
在使用 Zend Framework(以下简称 ZF) 框架的时候,其中的 Zend_Controller 会自动加载一个名为 ViewRenderer 的插件,它会根据所请求的控制器和动作名来显示一个视图脚本(即模板),也就是说,使用 Smarty 的时候,不用实例化 Smarty 类或者调用 display() 方法来输出模板,因为 ViewRenderer 会为我们做这些工作。
要想让 Zend 与 Smarty 交互,我们必须扩展 Zend_View_Abstract 类从而达到我们的目的,可以创建一个 Templater 的类,之后就要在 index.php 引导文件中告诉 Zend_Controller 这个类的信息。
先来看看应用的文件目录信息:
来简要的介绍一下:
data:用来存放应用相关的数据文件:
htdocs:这个是应用的根目录,里面暂时只有一个 index.php 文件。(截图舍去)
include:这里存放主要的库文件:ZF,Smarty…等一些需要“包含”的文件:(PHP 的 include_path 项已经包含了此目录)
templates:这里存放模板文件:(暂时只有一个 index 控制器模板目录)
httpd.conf:Apache 的子配置文件。(已经包含进了 Apache 的主文件里,这里不做介绍了)
settings.ini:站点配置文件:
-----------------------应用文件目录信息结束,来看看如何创建 Templater 类呢?
我们将把这个类放入应用的 include/ 文件夹中,看一下第三个截图中的 Templater.php,这就是我们将要创建的类文件。另外呢,我们还要在 include/Templater/ 文件夹中创建一个 plugins/ 的目录,就像这样:include/Templater/plugins/ ,这个目录可以用来存放所有定制 Smarty 插件,通过将我们自己的所有扩展插件存放在一个单独的目录中,可以很容易地升级到 Smarty 的最新版本,而不必总是跟踪我们的哪些文件需要移动。
现在可以着手创建 Templater.php 了,在其中指定 Smarty 的 template_dir(模板路径)和 compile_dir(编译路径),还要告诉 Smarty ,除去自己的 plugins 目录外,还可以在 include/Templater/plugins/ 中寻找插件。
要实现这个类,必须实现一些关键的方法,使得 ViewRenderer 能够与 Smarty 交互,其中最重要的方法如下:
> getEngine()。此方法必须返回 Smarty 的一个实例。由于这个方法可能被调用多次,所以应当将 Smarty 实例缓存起来,这样就只需创建一次实例。为此,将在构造函数中创建 Smarty 对象;
> __set()。此方法将一个变量赋给模板。实际上,这意味着可以在任何控制器动作中将 $smarty->assign('foo', 'bar') 替换为 $this->view->foo = 'bar'。
> __get()。此方法返回一个先前赋给模板的变量。
> render()。此方法显示一个模板。它的效果与调用 $smarty->display 类似,只不过这个方法要返回输出(而不会直接显示),故必须在 Smarty 对象上使用 fetch() 而不是 display()。
下面的代码则展示了 Templater.php 的代码,注意要与 Zend 框架的类命名结构相一致,这也意味着必须将这个类放在 include/ 目录中。
Templater.php:
<?php
class Templater extends Zend_View_Abstract
{
protected $_path;
protected $_engine;
public function __construct()
{
$config = Zend_Registry::get('config');
require_once('Smarty/Smarty.class.php');
$this->_engine = new Smarty();
$this->_engine->template_dir = $config->paths->templates;
$this->_engine->compile_dir = sprintf('%s/tmp/templates_c',
$config->paths->data);
$this->_engine->plugins_dir = array($config->paths->base .
'/include/Templater/plugins',
'plugins');
}
public function getEngine()
{
return $this->_engine;
}
public function __set($key, $val)
{
$this->_engine->assign($key, $val);
}
public function __get($key)
{
return $this->_engine->get_template_vars($key);
}
public function __isset($key)
{
return $this->_engine->get_template_vars($key) !== null;
}
public function __unset($key)
{
$this->_engine->clear_assign($key);
}
public function assign($spec, $value = null)
{
if (is_array($spec)) {
$this->_engine->assign($spec);
return;
}
$this->_engine->assign($spec, $value);
}
public function clearVars()
{
$this->_engine->clear_all_assign();
}
public function render($name)
{
return $this->_engine->fetch(strtolower($name));
}
public function _run()
{ }
}
?>
好了,我们的 Templater 类已经完成了,怎样来使用呢?我们需要让 Zend_Controller 使用 Templater 类,而不是默认的 Zend_View 类。为此,我们必须要将下面的代码加入到应用的引导文件(index.php)中:
// setup the view renderer
$vr = new Zend_Controller_Action_Helper_ViewRenderer();
$vr->setView(new Templater());
$vr->setViewSuffix('tpl');
Zend_Controller_Action_HelperBroker::addHelper($vr);
(关于这里的 ZF 知识,请看文章最下方的 ViewRenderer 介绍)
注意,必须要调用 setViewSuffix() 来指示模板以文件扩展名 .tpl (或者 .htm …)结尾,默认地,Zend_View 使用 .phtml ,来看看我们现在的 bootstrap(引导文件 htdocs/index.php,即应用的引导文件):
index.php:
<?php
/*Old:
require_once('Zend/Loader.php');
Zend_Loader::registerAutoload();
*/
/*ZF 的自动加载机制*/
require_once('Zend/Loader/Autoloader.php');
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->setFallbackAutoloader(true);
// load the application configuration(导入应用的配置文件)
$config = new Zend_Config_Ini('../settings.ini', 'development');
Zend_Registry::set('config', $config);
// create the application logger(加载 ZF 的日志机制)
$logger = new Zend_Log(new Zend_Log_Writer_Stream($config->logging->file));
Zend_Registry::set('logger', $logger);
// connect to the database(数据库配置及连接)
$params = array('host' => $config->database->hostname,
'username' => $config->database->username,
'password' => $config->database->password,
'dbname' => $config->database->database);
$db = Zend_Db::factory($config->database->type, $params);
Zend_Registry::set('db', $db);
// handle the user request(处理用户请求)
$controller = Zend_Controller_Front::getInstance();
$controller->setControllerDirectory($config->paths->base .
'/include/Controllers');
// setup the view renderer(这里是我们新加的,用来处理 ViewRenderer)
$vr = new Zend_Controller_Action_Helper_ViewRenderer();
$vr->setView(new Templater());
$vr->setViewSuffix('tpl');
Zend_Controller_Action_HelperBroker::addHelper($vr);
$controller->dispatch();
?>
现在,一旦执行一个控制器动作,Zend_Controller 就会根据控制器名和动作名自动查找模板。下面使用 index 控制器的 index 动作作为一个简单的测试例子:
在我们的 include/Controllers/ (用来存放各种控制器)目录中的:IndexController.php:
IndexController.php:
<?php
class IndexController extends CustomControllerAction
{
public function indexAction()
{
}
}
?>
注意:CustomControllerAction 类:
CustomControllerAction.php:
<?php
class CustomControllerAction extends Zend_Controller_Action
{
public $db;
function init()
{
$this->db = Zend_Registry::get('db');
}
}
?>
相应的 index 控制器的 index 动作的模板:templates/index/index.tpl:
index.tpl:
{include file='header.tpl'}
Web site home
{include file='footer.tpl'}
至此呢,所有的整合工作都已完成,进入应用站点看看是不是显示:
是的话,就整合成功了!
--------------------------------------------------------------------------以下为附录部分:
ViewRenderer 介绍:
视图解析 (ViewRenderer) 助手为实现下列目标设计:
-
不需要在控制器内创建视图对象实例;视图对象将在控制器内自动注册。
-
根据当前的模块自动地设置视图脚本、助手、过滤器路径。指派当前的模块名为助手和过滤器类的类名前缀。
-
为所有分发的控制器和动作创建全局有效的视图对象。
-
允许开发人员为所有控制器设置默认的视图解析选项。
-
加入无需干预自动解析试图脚本的功能。
-
允许开发人员为视图基路径和视图脚本路径创建自己的规范。
注意
如果手动执行_forward()、redirect、或者render时,不会发生自动解析。因为执行这些动作时,等于告诉 ViewRenderer,你要自己确定输出结果。
ViewRenderer 助手默认启用。你可以通过前端控制器的 noViewRenderer 方法、设定参数 ($front->setParam('noViewRenderer', true)) 或者从助手经纪人栈 (helper broker stack) 中移除助手 (Zend_Controller_Action_HelperBroker::removeHelper('viewRenderer')) 等方式禁用该助手。
创建实例并注册自己的 ViewRenderer 对象,然后传入到助手经纪人:
$viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer();
$viewRenderer->setView($view)
->setViewSuffix('php');
Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
通过助手经纪人即时的初始化并/或获取ViewRenderer对象:
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
$viewRenderer->setView($view)
->setViewSuffix('php');
更多相关的资料可以查看 ZF 的在线 Manual(手册):http://framework.zend.com/manual/zh/zend.controller.html


浙公网安备 33010602011771号