这两天对项目用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}> 这种形式来使用助手类了
|