昨天小蕊叫我调试错误,把整个网站丢过来,那里面的HTML代码海洋让我看得七荤八素,郁闷无比,已经好久没有看到这样的一大堆HTML混合少量PHP的代码了。
其实PHP的层次升级过程就是不断的分层、提炼、抽象的过程,一旦对某种模式稍微巩固,就应该思考如果避开这种模式的缺陷。反正我到目前为止,每当重复写以前曾实现过的代码时,必定要用比前次更好的方法(或另外的途迳)来实现,否则代码写得再多也只是量变,无法产生质变
唠叨完了,现在切入正题吧,这次试试采用问答式写法。
一。什么是模板?
使用模板引擎可以使业务逻辑与显示逻辑分开——这是很欠扁但也是网上公认的说法,呃,说得很准确,但估计只有会使用模板的人才能理解……其实刚开始大可以简单的理解模板为“PHP与HTML代码分离的方法”。
二。为什么要使用模板技术?
让程序(PHP层)与显示(HTML层)分离可以使代码更清晰易懂,要修改程序问题就去PHP层找,要改显示问题就去HTML层改。更重要的是这样的设计可以让不懂PHP的前台美工也能修改页面。如果不是很理解没关系,你只要知道这是迈向其它高级开发模式的必经之路就可以了。
三。有哪些模板技术?
我使用过PHPLIB库中的模板类,后来又使用了smarty和smartyLight,也试过原生的PHP方式实现的模板,现在大家基本上都用smarty。PHP方式相对来说最容易实现,学得也快,但不适合团队合作。
四。smarty广被攻击的“弱点”
smarty的语法太复杂,学它简直就是学一门新语言——其实你不需要复杂的功能,它就简单得很,如果你需要它复杂的功能,那你应该感谢它!根据我的经验,刚开始用一个东西,大家都喜欢简洁精炼,但随着应用的复杂,大多会抱怨它功能不足……
smarty有几百K,它太大了,慢!——其实大小与速度不成正比,smarty有编译缓存和静态缓存机制,甚至可以局部缓存
另外它的自定义插件用起来非常爽,modify,block等,我这几天正用它的block来输出页面组件。
 五。下载,配置smarty
因为我后来一直用smarty的简化版smartyLight,它们的语法大部分相同但也有不同,所以没办法把我现在的代码搬出来以免出错,好吧,为了写这篇,我去下载完整版smarty。
下载2.6.18版的吧,最新的是2008的,不一定很稳定
其它目录都删了,保留libs目录就可以了,如果为了学习可以保留demo目录。
六。实战
使用模板引擎后,PHP代码与模板分离了,一般写一个应用都有PHP和HTML两个页面
PHP部分有三个部分组成:载入与配置、赋值、载入模板解析,其中第一部分是公用的,也就是放到公共页里以后都不需要再写的。第三部分即dispay方法,就一行代码,所以重点在第二部分。
(注:数组都分索引数组和关联数组两种来说明,索引数组即以数字为键的数组,关联数组是每个键有个字符串名称的数组,实在不理解就翻书去)
A。普通变量赋值与使用.
PHP代码
  1. header('Content-Type:text/html;charset=utf-8');   
  2. require '../libs/Smarty.class.php';   
  3.   
  4. $smarty = new Smarty;   
  5.   
  6. $smarty->compile_check = true;   
  7. $smarty->debugging = false; //调试时设为true   
  8.   
  9. //以上操作通常在包含页里,也就是说和数据库链接那样的操作类似,写一次就行了,根本不用记   
  10. //下面是实际的代码,PHP部分没啥难的,各种类型的变量,数组,对象统统可以用assign方法赋值给模板.   
  11. $smarty->assign("name","星野天河");                     //这句是第二部分。普通的变量   
  12. $smarty->display('index.tpl'); //载入模板  
 最后一句的display方法是载入默认模板目录下的index.tpl模板,当然可以修改默认的模板目录。假如要改到abc目录。(不要照抄啊,出错我不负责)
PHP代码
  1. $smarty->template_dir = '/abc/';  
模板部分(本例为index.tpl文件)
XML/HTML代码
  1. 普通变量的使用格式: {$name}<br>  
 这样大括号中的内容会被上面11行定义的name值代替。使用这个你可以把网页标题,关键字,站长名字、图片路径、js路径、网站根目录、文档根等信息都在包含页里直接赋值了(一次性操作),之后在模板里任何地方可以直接使用。路径问题也不至于错乱,修改起来也省事。
B。一维索引数组的赋值与使用
PHP代码
  1. $smarty->assign("persons",array("星野天河","小蕊","天空","西",'奶瓶'));  
将数组丢给$persons变量,html中循环输出数组有两种格式。第一种如下
XML/HTML代码
  1. {section name=item loop=$persons}   
  2.     {$persons[item]}<br>  
  3. {/section}  
section是smarty的循环结构, loop表示要循环哪个变量,这里是$persons这个变量(上面PHP代码中赋值的数组),name表示循环中的每一项值用什么表示,可以随便取名的,例如叫item,那下面就要用{$persons[item]}表示数组中的一个项。
不过我更习惯使用第二种模式——foreach循环,因为与PHP格式接近,容易理解,并且更重要的是——省代码!效率也高些,记住下面的格式。
XML/HTML代码
  1. {foreach item=person from=$persons}   
  2.     {$person}<br>  
  3. {/foreach}  
可以理解为把$persons数组拆开,每一项都丢进person变量中,与以下PHP代码完全一样。所以,把section忘了吧。
PHP代码
  1. foreach($persons as $person){   
  2.         echo $person;   
  3. }  
C。一维关联数组
如果是一维相关数组的话,那更简单,不需要使用循环了。
PHP代码
  1. $smarty->assign("user",array('name'=>"星野天河",'iq'=>138, 'qq'=>15957674));    //一维相关数组的赋值  
XML/HTML代码
  1. 一维关联数组的使用: {$user.name}: {$user.iq} {$user.qq}  
看见了吧,简单透顶,{$user.name}相当于PHP中的{$user['name']},这点和smarty简化版不同(我更喜欢后者的格式{$user[name]}
D.二维索引数组
PHP代码
  1. $smarty->assign("all"array(array(1,2,3,4,5), array(6,7,8,9,10), array(11,12,13,14,15)));   
XML/HTML代码
  1. {foreach item=nums from=$all}   
  2.     {foreach item=num from=$nums}   
  3.         {$num}   
  4.     {/foreach}   
  5.     <br>  
  6. {/foreach}  
如果对操作PHP数组熟练,很容易理解这种循环镶套,第一轮把$all二维数组中的每一个元素拆到$nums变量中,第二轮再把$nums变量(这里是一维数组了)拆开丢进$num变量中.
E。二维关联数组的使用
PHP部分
PHP代码
  1. $smarty->assign("guests"array(   
  2.        array("title" => "第一条留言的标题""content" => "第一条标题的内容""author" => "留言者小蕊"),           
  3.         array("title" => "第二条留言""content" => "今天带笔了,要签名的排队""author" => "星野大叔"))   
  4. );  
实际的应用中,这个二维数组通常是数据库输出结果,所以为了模板使用方便,用db类吧,直接输出数组的那种.赶紧扔了那种wliel($row=mysql_fetch_assoc($rs)){ //一堆操作 }使用数据库的方式.
回归正题,看一下模板里怎么用二维关联数组吧.这回我不说累赘的section模式了.看foreach
XML/HTML代码
  1. {foreach item=guest from=$guests}   
  2.     {$guest.title}<br>  
  3.     <p>{$guest.content}</p>  
  4.     留言者:{$guest.author}<br>  
  5. {/foreach}  
应该能够理解,将二维数组中的每一个元素(通常是数据库中的每一条记录)扔进guest变量中,这个变量就是一维相关数组了,使用方式与一维相关数组完全相同.
F.三维,四维……
二维及其以上的数组都分不清是索引还是关联数组了,很可能是混合型的,但都是以以一维数组的方式为基的,只要理解数组的每一维属于哪种,用正常的方法解开(以上两种方式之一)一层一层解开就行了,不要看到N维数组就头痛。
呃说了一大堆,发现我只说数组,没有说对象如何使用,这是因为我大多用数组的关系,对象的循环与数组一样,只不过内部的使用格式不同罢了,可能{$item.id}变成{$item->id}这样子,因为很少用对象模式输出数据库内容,又一直用smartyLight,所以smarty的记不清了,但要使用的时候上百度,一分钟内就能找到答案。
 附:
一般默认配置就可以使用了,但要更好的使用可能需要改一下配置。
PHP代码
  1. $tpl->template_dir = __SITE_ROOT . "/templates/";    
  2. $tpl->compile_dir = __SITE_ROOT . "/templates_c/";    
  3. $tpl->config_dir = __SITE_ROOT . "/configs/";    
  4. $tpl->cache_dir = __SITE_ROOT . "/cache/";    
  5. $tpl->left_delimiter = '<{';    
  6. $tpl->right_delimiter = '}>';  
 template_dir是模板目录,compile_dir是编译目录(不理解没关系,但必须有这个目录),最后两个是模板中使用变量的包含符,可以不用大括号以避开与js的冲突。这是因为js中有大括号
不过我还是喜欢用大括号做包含符,因为简单与习惯,也有办法避开js冲突。例如
XML/HTML代码
  1. <script>  
  2. {literal}   
  3. function abc(){   
  4.     //包含在{literal}中的代码不会被模板引擎解析,所以js中的大括号就与模板的大括号无关了。   
  5. }   
  6. {/literal}   
  7. </script>  
  8.   
要注意只有在js中有大括号的时候才需要用literal包含,如果只是外链的js就不需要了,因为没有大括号。js的冲突与解决方法同样适合于css代码。改模板包含符还是使用literal看你喜好了
 
总结:
其实用smarty还是很简单的,只不过把使用变量的方式改一下、再用DB类直接输出数组代替原来的过程式写法(如果不这么做,使用smarty会比较麻烦),重点就是记格式了,理解上没有难点。
附带说个非常有用的功能
XML/HTML代码
  1. {include file="header.tpl" title=foo}  
 在模板中可以用这个加载其它模板,而且你赋值的变量,在载入页 (header.tpl)中仍然可以使用,不像phplib模板类那样还要再赋值。后面带的参数任意,title=foo表示在header.tpl页中,$title变量值改为foo,这很有用,因为头文件中,通常标题,关键字,css文件路径要重新定义的。
之后的进阶功能还有很多,不过做为入门教程,这里写的已经可以打发一段时间了,高级功能嘛,有朋友问的时候再写,俺一向比较懒