yaf(5) smarty

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 2013年4月6日 13:41:37 参考: http://www.oschina.net/question/812776_71817 http://yaf.laruence.com/manual/yaf.

2013年4月6日 13:41:37

参考:

http://www.oschina.net/question/812776_71817

http://yaf.laruence.com/manual/yaf.class.dispatcher.setView.html

这两者都是在bootstrap.php中写_initSmarty()函数来重新实现yaf的视图接口

这中方案默认的是存放模版文件的上级文件夹名字必须是views

根据项目要求,要求可以自定义存放模版文件的文件夹名字,过程及注意事项记录如下:

1.没有在bootstrap.php中写_initSmarty()函数来重新实现yaf的视图接口,而是在路由结束时的hook代码中来重写视图接口

hook 
 1 <?php
 2 class LayoutPlugin extends Yaf_Plugin_Abstract {
 3 
 4     public function routerStartup(Yaf_Request_Abstract $request, Yaf_Response_Abstract $response) {
 5         echo "Plugin routerStartup called <br/>\n";
 6     }
 7 
 8     public function routerShutdown(Yaf_Request_Abstract $request, Yaf_Response_Abstract $response) {
 9         echo "Plugin routerShutdown called <br/>\n";
10         //整合smarty
11         $dispatcher = Yaf_Dispatcher::getInstance();
12 //         $dispatcher->disableView();
13         $dispatcher->autoRender(false);
14         $objSmarty = new Smarty_Adapter;
15         $dispatcher->setView($objSmarty);
16         
17     }
18 
19     public function dispatchLoopStartup(Yaf_Request_Abstract $request, Yaf_Response_Abstract $response) {
20         echo "Plugin DispatchLoopStartup called <br/>\n";
21     }
22 
23     public function preDispatch(Yaf_Request_Abstract $request, Yaf_Response_Abstract $response) {
24         echo "Plugin PreDispatch called <br/>\n";
25     }
26 
27     public function postDispatch(Yaf_Request_Abstract $request, Yaf_Response_Abstract $response) {
28         echo "Plugin postDispatch called <br/>\n";
29     }
30 
31     public function dispatchLoopShutdown(Yaf_Request_Abstract $request, Yaf_Response_Abstract $response) {
32         echo "Plugin DispatchLoopShutdown called <br/>\n";
33     }
34 }

此时可以确保yaf已经分析URL完毕,确定了moduleName,controllerName,ActionName,

此时重写yaf视图接口就可以根据不同的moduleName去设定不同的smarty模版目录

注意几点:

①在bootstrap.php中写_initSmarty()函数来重新实现yaf的视图接口:

1 //smarty
2     public function _initSmarty(Yaf_Dispatcher $dispatcher)
3     {
4         var_dump('@@@@@@@@@');
5     }

结果:

1 string '@@@@@@@@@' (length=9)
2 
3 Plugin routerStartup called
4 Plugin routerShutdown called
5 Plugin DispatchLoopStartup called
6 Plugin PreDispatch called
7 Plugin postDispatch called
8 Plugin DispatchLoopShutdown called 

说明:在分析URL得到 moduleName,controllerName,ActionName 之前已经执行了_initSmarty();如果在这里边重写接口,灵活性就不是很大


② 关闭yaf自动默认的display动作(hook代码的第13行:$dispatcher->autoRender(false);)

否则yaf在执行完action内的代码后会根据当前的controllerName和actionName去尝试加载controllerName/actionName.html,如果加载不到就会抛出异常:

e.g. 访问本地:www.yaftwo.com/test/index/aaa时,打开自动默认的display动作

1 Plugin routerStartup called
2 Plugin routerShutdown called
3 Plugin DispatchLoopStartup called
4 Plugin PreDispatch called
5 -------smarty say hello to you !-------
6 
7 object(SmartyException)[24]
8   protected 'message' => string 'Unable to load template file 'F:/zzbserv/apache/htdocs/yaftwo/code/application/modules/test/templates/index\aaa.html'' (length=117)
9 ...

说明:第5行的输出说明已经成功display,但是紧接着就抛出了异常,内容很明显是因为找不到默认的disply路径

2.重写yaf视图接口

View Code
 1 <?php
 2 /*
 3  * 自定义视图类接口,用来封装smarty共yaf全局使用
 4  * 必须实现接口定义的5个函数
 5  */
 6 class Smarty_Adapter implements Yaf_View_Interface
 7 {
 8     public $_smarty;
 9     private $_script_path;
10     
11     public function __construct()
12     {
13         require 'Smarty.class.php';
14         $this->_smarty = new Smarty;
15         $this->_smarty->left_delimiter = "<{";
16         $this->_smarty->right_delimiter = "}>";
17         $this->_smarty->setCompileDir(ROOT.'/templates_c');//编译目录
18         $this->_smarty->setCacheDir(ROOT.'/cache');//缓存目录
19         //根据不同的模块设置不同的模版路径
20         $dispatcher = Yaf_Dispatcher::getInstance();
21         $arrRequest = $dispatcher->getRequest();
22         if (empty($arrRequest->module)) {
23             $this->_script_path = APP.'/templates';
24             $this->setScriptPath(APP.'/templates');
25         } else {
26             $strModuleName = strtolower($arrRequest->module);
27             $this->_script_path = APP.'/modules/'.$strModuleName.'/templates';
28             $this->setScriptPath(APP.'/modules/'.$strModuleName.'/templates');
29         }
30     }
31     
32     //返回要显示的内容
33     public function render( $view_name ,  $tpl_vars = NULL )//string
34     {
35         $view_path = $this->_script_path.'/'.$view_name;
36         $cache_id     = empty($tpl_vars['cache_id']) ? '' : $tpl_vars['cache_id'];
37         $compile_id = empty($tpl_vars['compile_id']) ? '' : $tpl_vars['compile_id'];
38         return $this->_smarty->fetch($view_path, $cache_id, $compile_id, false);//返回应该输出的内容,而不是显示
39     }
40     
41     //显示模版
42     public function display( $view_name, $tpl_vars = NULL )//boolean
43     {
44         $view_path = $this->_script_path.'/'.$view_name;
45         $cache_id     = empty($tpl_vars['cache_id']) ? '' : $tpl_vars['cache_id'];
46         $compile_id = empty($tpl_vars['compile_id']) ? '' : $tpl_vars['compile_id'];
47         return $this->_smarty->display($view_path, $cache_id, $compile_id);
48     }
49     
50     //模版赋值
51     public function assign( $name, $value = NULL )//boolean
52     {
53         return $this->_smarty->assign($name, $value);
54     }
55     
56     //设定脚本路径
57     public function setScriptPath( $view_directory )//boolean
58     {
59         return $this->_smarty->setTemplateDir($view_directory);
60     }
61     
62     //得到脚本路径
63     public function getScriptPath()//string
64     {
65         return $this->_script_path;
66     }
67     
68 }

注意几点:
① setScriptPath()接口函数内不要写判断模版路径是否存在的代码,因为除了在重写视图接口时会执行这行代码外,yaf还会在"分发请求前"默默的执行这个函数,并且传递给它的实参是yaf默认的视图存放路径:views/actionName,此时如果你的layout中没有这个路径的话,你的程序就会报错

帖代码看看这个成员函数什么时候会被执行:

1 //设定脚本路径
2     public function setScriptPath( $view_directory )//boolean
3     {
4         var_dump('setScriptPath called with param '.$view_directory);
5         return $this->_smarty->setTemplateDir($view_directory);
6     }

 

 1 Plugin routerStartup called
 2 Plugin routerShutdown called
 3 
 4 string 'setScriptPath called with param F:/zzbserv/apache/htdocs/yaftwo/code/application/modules/test/templates' (length=103)
 5 
 6 Plugin DispatchLoopStartup called
 7 Plugin PreDispatch called
 8 
 9 string 'setScriptPath called with param F:/zzbserv/apache/htdocs/yaftwo/code/application/modules/Test/views' (length=99)
10 
11 -------smarty say hello to you !-------
12 Plugin postDispatch called
13 Plugin DispatchLoopShutdown called 

说明:下边代码块第4行的输出是因为那里我们重写了视图接口,在构造函数中调用了此函数;

但是第9行的输出则是在执行action时的自动调用输出,根据传入的实参可以知道这是yaf自己调用的(现在我还不知道如何去阻止这个调用)

②注意重写接口的diaplay();函数时,要手动拼接上模版文件的绝对路径,这里再贴一遍代码:

1 //显示模版
2     public function display( $view_name, $tpl_vars = NULL )//boolean
3     {
4         $view_path = $this->_script_path.'/'.$view_name;
5         $cache_id     = empty($tpl_vars['cache_id']) ? '' : $tpl_vars['cache_id'];
6         $compile_id = empty($tpl_vars['compile_id']) ? '' : $tpl_vars['compile_id'];
7         return $this->_smarty->display($view_path, $cache_id, $compile_id);
8     }

说明:注意第4行手动拼接上模版文件的绝对路径(不用管第5,6行代码),这样yaf就可以找到自己定义的模版目录下的模版了,否则:

1 Plugin routerStartup called
2 Plugin routerShutdown called
3 Plugin DispatchLoopStartup called
4 Plugin PreDispatch called
5 
6 object(SmartyException)[21]
7   protected 'message' => string 'Unable to load template file 'test.html'' (length=40)
8 ...

最后贴出重写后的用法:

1 <?php
2 class IndexController extends Yaf_Controller_Abstract 
3 {
4     public function aaaAction()
5     {
6         $this->getView()->assign('var', 'smarty say hello to you !');
7         $this->getView()->display('test.html');
8     }
9 }


另外:

①我在刚接触zend framework的时候,也整合过smarty当时用的是它的全局变量注册功能,我看到yaf的在线手册里也有此类(Yaf_Registry),有用到的可以试试

②Yaf_Controller_Abstract中有个默认执行的init()函数,也可以打打它的注意(*^__^*)

完.

 

目录
相关文章
|
人工智能
新手必看,写歌词的技巧和方法新分享,妙笔生词AI智能写歌词软件
对于新手,写歌词不再难。本文分享了写歌词的实用技巧,如积累生活素材、明确主题、合理安排主副歌、简洁有力的语言表达等。推荐使用“妙笔生词智能写歌词软件”,其AI功能可助你灵感不断,轻松创作。
|
新零售 自然语言处理 运维
一文详解 | 开放搜索兼容Elasticsearch做召回引擎
开放搜索发布开源兼容版,支持阿里云Elasticsearch做搜索召回引擎,本文详细介绍阿里云ES用户如何通过接入开放搜索兼容版丰富行业分词库,提升查询语义理解能力,无需开发、算法投入,即可获得淘系同款搜索效果。
1881 0
|
供应链 安全 区块链
构建未来:智能合约在区块链技术中的应用与挑战
【5月更文挑战第29天】 随着区块链技术的不断演进,智能合约作为其核心创新之一,正逐渐改变着我们的商业逻辑和交易模式。本文深入探讨了智能合约的技术原理、实际应用案例以及面临的主要挑战。我们将从智能合约的定义出发,解析其如何通过自动执行合同条款来减少中间环节,提高交易效率。同时,文章还将审视智能合约在不同行业中的实际应用,包括金融服务、供应链管理和身份验证等。最后,本文将讨论智能合约目前存在的技术限制、安全性问题以及法律监管的挑战,并提出对未来智能合约发展的展望。
699 0
|
存储 安全 Java
Java修仙之路,十万字吐血整理全网最完整Java学习笔记(进阶篇)
本文是Java基础的进阶篇,对异常、集合、泛型、Java8新特性、I/O流等知识进行深入浅出的介绍,并附有对应的代码示例,重要的地方带有对性能、底层原理、源码的剖析。适合Java初学者。
Java修仙之路,十万字吐血整理全网最完整Java学习笔记(进阶篇)
|
前端开发 数据可视化 Java
前后端分离项目部署上线详细教程
前后端分离项目部署上线详细教程
|
存储 JSON 分布式计算
MaxCompute半结构化数据思考与创新
本文将介绍MaxCompute在半结构化数据方面的一些思考与创新,围绕半结构化数据简析、传统方案优劣对比、MaxCompute半结构化数据解决方案、收益分析。
786 11
|
编解码 定位技术 Sentinel
Google Earth Engine(GEE)——Sentinel-3 OLCI EFR:海洋和陆地彩色地球观测全分辨率数据集
Google Earth Engine(GEE)——Sentinel-3 OLCI EFR:海洋和陆地彩色地球观测全分辨率数据集
546 0
Google Earth Engine(GEE)——Sentinel-3 OLCI EFR:海洋和陆地彩色地球观测全分辨率数据集
|
弹性计算 自然语言处理 达摩院
2022云栖精选—阿里云智能客服从提升生产力到提升客户忠诚度
摘要:本文整理自达摩院创新业务中心负责人聪云,在云栖大会的分享。本篇内容主要分为三个部分: 1. 背景概览 2. 升级新体验 3. 畅想未来
1370 0
2022云栖精选—阿里云智能客服从提升生产力到提升客户忠诚度
|
机器学习/深度学习 Web App开发 人工智能
全球名校AI课程库(8)| Berkeley伯克利 · 全栈深度学习训练营课程『Full Stack Deep Learnin』
课程以实战为主,讲解了不同场景下应用深度学习解决问题的工具、过程和方法:从问题理解,方法选择、数据管理、选择 GPU 到 Web 部署、监控和再训练。
2560 1
全球名校AI课程库(8)| Berkeley伯克利 · 全栈深度学习训练营课程『Full Stack Deep Learnin』
|
机器学习/深度学习 人工智能 自然语言处理
全球名校AI课程库(15)| Stanford斯坦福 · 线性代数与矩阵方法导论课程『Introduction to Applied Linear Algebra』
快速补充线性代数的必选课程!课程用了非常多的例子和图标,来直观地表示向量、矩阵与复杂世界的关系,并将数学转化为解决工程问题的能力。
2474 1
全球名校AI课程库(15)| Stanford斯坦福 · 线性代数与矩阵方法导论课程『Introduction to Applied Linear Algebra』