这两天对项目用zf 1.7进行重构。基于种种原因,项目的视图需要用smarty来完成。关于zf结合smarty,网上有很多资料。换用smarty和发现一个问题,就是 zf的各种视图助手无法使用了。在网上的了好久,也没有见到任何资料。狠下心来,把zf的源码看了一遍终于找到解决方案。在这里记录一下:
一、集成smarty
1.首先需要根据Zend_View_Interface接口编写ZF的Smarty视图类,假设你在library创建在
library/View/这样的文件目录结构,同时假设你下载的Smarty类库也在library目录中。在library/View/下新建 Smarty.php,然后按照手册中的说明,编写Zend_View_Smarty类实现Zend_View_Interface接口,代码如下:
<?php
/**
* 实现一个Zend View 的一个接口
* author:xydream@gmail.com
*/
require_once 'Zend/View/Interface.php';
require_once 'Smarty/Smarty.class.php';
class Zend_View_Smarty extends Zend_View_Abstract implements Zend_View_Interface
{
/**
* Smarty 对象
* @var Smarty
*/
protected $_smarty;
/**
* 构造函数
* @param string $tmplPath
* @param array $extraParams
* @return void
*/
public function __construct ($tmplPath = null, $extraParams = array())
{
$this->_smarty = new Smarty();
if (null !== $tmplPath) {
$this->setScriptPath($tmplPath);
}
foreach ($extraParams as $key => $value) {
$this->_smarty->$key = $value;
}
}
/**
* 返回模板引擎对象
* @return Smarty
*/
public function getEngine ()
{
return $this->_smarty;
}
/**
* 设置存放模板文件的路径
* @param string $path 要作为路径的目录.
* @return void
*/
public function setScriptPath ($path)
{
if (is_readable($path)) {
$this->_smarty->template_dir = $path;
return;
}
throw new Exception('Invalid path provided');
}
/**
* 返回当前存放模板文件的路径
* @return string
*/
public function getScriptPaths ()
{
return array(
$this->_smarty->template_dir);
}
/**
* 配置Smarty引擎
*
* @param unknown_type $var
* @param unknown_type $value
*/
public function setupSmarty ($var, $value = '')
{
if (is_array($var)) {
foreach ($var as $k => $v) {
$this->setupSmarty($k, $v);
}
} else {
if (in_array($var, array(
'template_dir' ,
'compile_dir' ,
'cache_dir' ,
'caching' ,
'cache_lifetime' ,
'left_delimiter' ,
'right_delimiter'))) {
$this->_smarty->$var = $value;
}
}
return;
}
/**
* 获取Smarty配置
*
* @param unknown_type $var
* @return unknown
*/
public function getSmartySet ($var)
{
if (in_array($var, array(
'template_dir' ,
'compile_dir' ,
'cache_dir' ,
'caching' ,
'cache_lifetime' ,
'left_delimiter' ,
'right_delimiter'))) {
return $this->_smarty->$var;
}
}
/**
* 设置存放模板编译文件的路径
* @param string $path 要作为路径的目录.
* @return void
*/
public function setCompilePath ($path)
{
if (is_readable($path)) {
$this->_smarty->compile_dir = $path;
return;
}
throw new Exception('Invalid path provided');
}
/**
* 返回当前存放模板编译文件的路径
* @return string
*/
public function getCompilePaths ()
{
return array(
$this->_smarty->compile_dir);
}
/**
* 设置存放模板缓存文件的路径
* @param string $path 要作为路径的目录.
* @return void
*/
public function setCachePath ($path)
{
if (is_readable($path)) {
$this->_smarty->cache_dir = $path;
return;
}
throw new Exception('Invalid path provided');
}
/**
* 返回当前存放模板缓存文件的路径
* @return string
*/
public function getCachePaths ()
{
return array(
$this->_smarty->cache_dir);
}
/**
* setScriptPath方法的别名
* @param string $path
* @param string $prefix Unused
* @return void
*/
public function setBasePath ($path, $prefix = 'Zend_View')
{
return $this->setScriptPath($path);
}
/**
* setScriptPath方法的别名
* @param string $path
* @param string $prefix Unused
* @return void
*/
public function addBasePath ($path, $prefix = 'Zend_View')
{
return $this->setScriptPath($path);
}
/**
* 为模板设置一个变量
* @param string $key 变量名
* @param mixed $val 变量值
* @return void
*/
public function __set ($key, $val)
{
$this->_smarty->assign($key, $val);
}
/**
* 返回一个已设置的模板变量值
* @param string $key 变量名
* @return mixed 变量值
*/
public function __get ($key)
{
return $this->_smarty->get_template_vars($key);
}
/**
* 允许用empty()和isset()去测试
* @param string $key
* @return boolean
*/
public function __isset ($key)
{
return (null !== $this->_smarty->get_template_vars($key));
}
/**
* 允许unset()一个对象的属性
* @param string $key
* @return void
*/
public function __unset ($key)
{
$this->_smarty->clear_assign($key);
}
/**
* 为模板设置一个变量
* 允许设置一个具体的值给一个具体的变量,或者传递一个数组,用key => value键值对的形式批量赋值。()
* @see __set()
* @param string|array $spec 变量名,或数组
* @param mixed $value 可选的。如果前一个参数是变量,这个值将赋给变量
* @return void
*/
public function assign ($spec, $value = null)
{
if (is_array($spec)) {
$this->_smarty->assign($spec);
return;
}
$this->_smarty->assign($spec, $value);
}
/**
* 清除所有已设置变量
* @return void
*/
public function clearVars ()
{
$this->_smarty->clear_all_assign();
}
/**
* 处理一个模板,并返回其输出。.
* @param string $name 要处理的模板.
* @return string 输出的内容.
*/
public function render ($name)
{
return $this->_smarty->fetch($name);
}
protected function _run ()
{
include func_get_arg(0);
}
}
2.接下来我们需要编写一个动作助手,把Smarty注册到控制器全局属性中,编写类Zend_Controller_Action_Helper_View,对应的目录结构为library目录中
Zend/Controller/Action/Helper/View.php,代码如下:
<?php
class Zend_Controller_Action_Helper_View extends Zend_Controller_Action_Helper_Abstract
{
protected $_smartyConfig;
protected $_tmpPath;
public function __construct($tmpPath,array $config){
$this->_smartyConfig=$config;
$this->_tmpPath=$tmpPath;
}
public function preDispatch ()
{
$smarty = new Zend_View_Smarty($this->_tmpPath, $this->_smartyConfig);
$this->getActionController()->view = $smarty;
}
}
3.然后在入口文件中前端控制器分发前添加动作助手,并进行smarty的配置。这里我将配置放一了配置文件中,具体代码:
//配置模板
$style = empty($_COOKIE['style'])?$config->smarty->template_dir:$_COOKIE['style'];
$viewBasePath = $config->smarty->template_base_dir;
$templates_dir = $viewBasePath . DIRECTORY_SEPARATOR . ltrim($style, '///');
if (! is_readable($templates_dir)) {
setcookie('style', false, 315554400, // strtotime('1980-01-01'),
$config->cookie->path,
$config->cookie->domain,
$config->cookie->secure
);
echo '你选择的风格不存在!调用默认风格进行显示';
exit();
}
$smartySetup = array(
'compile_dir' => $viewBasePath . $config->smarty->compile_dir ,
'cache_dir' => $viewBasePath . $config->smarty->cache_dir ,
'caching' => $config->smarty->caching ,
'cache_lifetime' => $config->smarty->cache_lifetime ,
'left_delimiter' => $config->smarty->left_delimiter ,
'right_delimiter' => $config->smarty->right_delimiter);
Zend_Controller_Action_HelperBroker::addHelper(new Zend_Controller_Action_Helper_View($templates_dir,$smartySetup));
这样就完成了zf和Smarty的集成。
二、让smarty使用Zend_View的助手功能(需修改smarty源文件)
1.在smarty.class.php中为类添加一个属性:var $_zend_view=null;
2.找到这个函数 function Smarty()然后改为 function Smarty($zend_view=NULL)
并在内部增加这样一个语句: $this->_zend_view=$zend_view;
3.增加一个函数
/**
* 为了使用zend_view而增加,使smarty内部可以自动调用助手类
*
*/
public function __call($name, $args)
{
return $this->_zend_view->__call($name,$args);
}
4.在Zend_View_Interface的实现类 smarty.php中将 $this->_smarty = new Smarty();改为: $this->_smarty = new Smarty(new Zend_View());
这样就可以在模板中以<{php}> echo $this->url(array('page' => $page)); <{/php}> 这种形式来使用助手类了
转自:http://hi.baidu.com/xydream/blog/item/e079dfef34161c3eacafd598.html