<?php
//==============================================================
//--------------------使用Smarty模板基本步骤-------------------
	/*
	使用Smarty前的工作:
		将Smarty中的libs文件夹拷贝到服务器目录下,其他文件可
	以删除,在libs文件夹中只用到Smarty.class.php文件,但其他
	文件在此类中用到不可删除。在libs目录同级的目录当下还要创
	建模板目录、编译目录还有被包含文件即配置文件init.inc.php,
	在配置文件中将要创建Smarty对象与使用Smarty对象前的一些设
	置。
	
	注意事项:
		在以路径方式访问模板、CSS、JS、图片等文件时,路径都
	要以主程序文件(index.php)为基目录去调用其他文件。
		在模板中以{include file=""}形式加载文件,将以Smarty
	对象中指定的模板目录为基目录。
	*/
	//将网站根目录做成绝对地址,以便在任何目录下都可找到。
	define("ROOT",pathinfo(__FILE__,PATHINFO_DIRNAME));
	//包含Smarty
	include_once ROOT."/libs/Smarty.class.php";
	//创建Smarty类	
	$tpl = new Smarty;
	
	//指定模板目录
	$tpl->template_dir = ROOT ."/tpl";
	//指定编译目录
	$tpl->compile_dir = ROOT ."/com";
	//配置文件目录
	$tpl->config_dir = ROOT ."/configs";
	//修改默认分隔符
	$tpl->left_delimiter='{';
	$tpl->right_delimiter='}';
	
	//要在模板输出的变量
	$title="This is a title";
	$content="This is body contents";
	
	//分配变量
	$tpl->assign("title",$title);
	$tpl->assign("content",$content);
	//设定模板
	$tpl->display("test.html");
//==============================================================
//--------------------------注释--------------------------------
	//模板中使用的的注释
	{* 注释内容 *}
//==============================================================
//---------------------分配与访问数组--------------------------
	//---------------------一维数组----------------------------
	//在php中分配数组
	$tpl->assign("arr",array("hello","how"));
	//在模板中访问数组
	{$arr[0]}
	{$arr[1]}
	//----------------------二维数组---------------------------
	//在php中分配数组
	$tpl->assign("arr",array(array("a","b"),array("c","d")));
	//在模板中访问二维数组
	{$arr[0][0]}
	{$arr[0][1]}
	{$arr[1][0]}
	{$arr[1][1]}
	//-----------------------关联数组--------------------------
	//----------------------------------------------------------
	//在php中分配数组
	$tpl->assign("arr",array("one"=>"Hello","two"=>"How"));
	//在模板中访问关联数组,用点的形式
	{$arr.one}
	{$arr.two}
	//----------------------------------------------------------
	//----------------------二维关联数组-----------------------
	$tpl->assign("arr",array("one"=>array("one"=>"Hello")));
	{$arr.one.two}
	//------------------------混合模式-------------------------
	{$arr.one[0]}
	{$arr[0].one}
//==============================================================
//----------------------分配与使用对象-------------------------
	//在php中分配
	$tpl->assign("per",new person("Stephen",10));
	//在模板中调用属性与方法
	{$per->name}
	{$per->age}
	{$per->say()}
//==============================================================
//----------------------分配并直接运算-------------------------
	//在分配
	$tpl->assign("num1",10);
	$tpl->assign("num2",20);
	//在模板中直接运算
	{$num1+$num2}
//==============================================================
//------------------用配置文件修改文件属性--------------------
	/*此功能用于动态修改模板中标签的样式,在模板中加入{con
	fig_load file="view.conf"}语句来加载配置文件,在php程序
	文件中(如初始化文件init.inc.php)用 $tpl->configs_dir="con
	figs";来指定配置文件存放目录。*/
	//1.配置文件view.conf文件中的内容
	border=10
	tbwidth=800
	color=red
	//配置文件目录修改方法,指定配置文件存放目录
	$tpl->configs_dir="configs";
	//2.模板文件内容
	<html>
	//(1).在模板中加载配置文件
	{config_load file="view.conf"}
	//(2).用{#xxx#}这种方式修改表格等的属性
	<table border="{#border#}" width="{#tbwidth#}" bgcolor="{#color#}">
	<tr><td>xxx</td></tr>
	</table>
	</html>
	//------------------为配置文件分区域-----------------------
	//在配置文件中用 [区域名] 形式加入区域
	//view.conf文件中
	//公共区域
	border=10
	tbwidth=500
	//区域一
	[One]
	border=30
	tbwidth=300
	//区域二
	[Two]
	border=20
	tbwidth=400
	//在模板文件中修改参数 section="区域"
	{config_load file="view.conf" section="One"}
//==============================================================
//-------------------在模板中直接使用的变量-------------------
	//$_GET["page"]在模板中直接使用,形式如下
	{$smarty.get.page}
	//$_SESSION["username"]="This is a username";
	{$smarty.session.username}
	//等等
	{$smarty.post.page}
	{$smarty.cookies.username}
	{$smarty.server.SERVER_NAME}
	{$smarty.env.PATH}
	{$smarty.request.username}
	//-------------------在模板中直接使用的常量---------------
	{$smarty.const.HOST}				//主机名
	{$smarty.const.__FILE__}			//正在使用的编译文件
	{$smarty.server.SCRIPT_FILENAME}	//正在访问的脚本文件名
	//--------------------在模板中访问配置文件-----------------
	/*访问配置文件,用法同{#border#},如:<tr bgcolor="<#co
	lor#>">与<tr bgcolor="<$smarty.config.border>">效果相同*/
	{$smarty.config.border}
	//--------------------获取当前服务器的时间-----------------
	//当前服务器的时间戳
	{$smarty.now}
	//使用变量调解器将时间戳转换为年月日格式
	{$smarty.now|date_format:"%Y-%m-%d %H:%M:%S"}
//===================在模板中使用php的函数=====================
	//-----------------------注册函数---------------------------
	/*先在php中将函数写好,再在函数的上面使用$tpl->register_
	function("modName","funName")方法将函数注册(即为函数在模板
	中分配使用该函数的使用名)。在模板中写上{modName one ="a"
	two = "b"}即可调用该函数,此种调用函数的方式是以数组形式
	传入参数,其中one、two为传入函数的关联数组的键名,a、b为
	键值。还可以将分配在模板中的变量作为参数传入函数*/
	//php文件中写入的内容
	require_once "../init.inc.php";
	$tpl->register_function("Hello","demo");
	function demo($args){
		return $args['one'].$args['two'].$args['three'];
	}
	$Hello = "Hello";
	$tpl->assign("one",$Hello);
	$tpl->display("Test.html");
	
	/*模板中调用函数的写法,其中$one为从php中
	分配到模板的变量,在此作为参数传入函数*/
	{Hello one="$one is shit " two=2 three=3}
	//输出内容为:Hello is shit 22333
	//-----------------------注册块标记------------------------
	/*用法同注册函数,不同点在于注册块属于双标记{hello color
	="red"}One More Time{hello},且标签中的内容在函数中是用
	另一个形参来接收,形如function Hello($args,$contents,&$a,
	&$b){}其中$contents用来接收标记块之间的内容,&$a与&$b为引
	用传值Smarty会传入参数。*/
	//注册块标记,将Test函数注册为Hello名
	$tpl->register_block("Hello","Test");
	/*第一个参数用来接收标签属性,第二个传标签中的属性,
	预留两个变量,采用引用传值*/
	function Test($args,$content,&$a,&$b){
		echo $args['red'].$args['size'].$args['num'].$content;
	}
	//在模板中使用快标记,并传入参数
	{Hello num=5 color="red" size="7"}
		//在内容中可加入变量
		Hello---{$Hello}---Hello<br>
	{/Hello}
	//------------------用插件的形式写函数---------------------
	/*在模板中也可以用插件的形式调用函数,在smarty插件目录下
	自定义一个函数文件在模板中即可调用该函数。不同的插件有
	不同的命名规则,以function开头的为函数文件,modifier开头
	的为变量调解器文件,以block开头的为块函数文件。操作流程
	如下:*/
	
	//插件目录 Smarty/libs/plugins
	//函数的插件文件命名规则:function.Name.php
	//函数名的书写规范:function smarty_function_Name(){}
	//传入函数的参数:参数数组,预留变量
	function smarty_function_Hello($args,&$smarty){
		print_r($args);
	}
	//在模板中直接调用函数
	{Hello num=6 color="red" size=7 content="Hello"}
	//-------------------插件形式加入块------------------------
	//插件目录 Smarty/libs/plugins
	//块函数文件命名规则:block.Name.php
	//块函数命名规范:function smarty_block_Hello(){}
	//传入函数的参数:参数数组,块中内容,预留变量
	function smarty_block_Hello($args,$content,&$smarty){
		print_r($args);
		echo $content;
	}
	//在模板中直接调用函数
	{Hello num=6 color="red" size=7}
		Hello--{$hello}--Hello<br>
	{/Hello}
//--------------------------------------------------------------
//--------------------Smarty中的自定义函数---------------------
	/*自定义函数即Smarty提供已定义好的函数,如下拉框标签{html
	_select_date}直接调用即可,而且可以任意修改任意添加。更多
	内容详见手册(函数中有常用的功能)*/
//==============================================================
//----------------------变量调解函数---------------------------
	/*变量调解器可以使数据直接在模板中处理,不必在程序中处理
	完成后再分配到模板,采用插件方式与采用分配函数方式都可以,
	本例采用插件方式*/
	//插件目录 Smarty/libs/plugins
	//命名规则:modifier.Name.php
	//模块文件书写规范如下
	//函数参数:任意参数
	function smarty_modifier_todx($Hello,$Hello1,$Hello2){}
	//在模板中使用变量调解器
	//调用形式:{分配的变量|函数名:"参数1":"参数2":"参数3"}
	{$str|todx:"Hello":"Hello1":"Hello2"}
	//组合使用变量调解器,函数在前的先调用
	{$str|todx:"Hello":"How"|demo:"Hello"}
	//Smarty中自带的函数调解器,详见手册
	truncate
	upper
//==============================================================
//-----------------------Smarty内建函数-------------------------
	/*Smarty内建函数和自定义函数类似,都可以再模板中直接使用
	不同的是内建函数不可以修改删除等操作,自定义函数可以修改
	删除等。*/
	//----------------------常用内建函数------------------------
	//此标签可以在模板中直接使用php代码
	{php}/*php的任何程序*/{/php}
	
	/*在模板中包含子模板或文件:子模板中的变量,只要向主模
	板中分配子模板变量即可。用include加载模板时被加载的文件
	成为此模板的一部分。*/
	{include file="header.tpl"}
	
	//从配置文件中加载变量
	{config_load file="colors.conf"}
	
	/*此标签将一个内容保存,在需要的地方将其输出。标签之间
	为要保存的内容,name为输出时用的调用名,用$Smarty.captu
	re.调用名,来调用输出。*/
	{capture name="Hello"}/*各种内容*/{/capture}
	//输出调用
	{$smarty.capture.Hello}
	//---------------模板中的if elseif else语句----------------
	//将变量分配给模板
	$tpl->assign("var",1);
	/*在模板中的书写格式:如果if后面的变量为真,则if中的内
	容才会执行,同php中的 if($var==1){} */
	{if $var == 1}			//开始标签
		Hello<br>
	{elseif $var == 2}		//不支持 if else
		Hello2<br>
	{else}
		Hello3<br>
	{/if}				//结束标签
	//-------------模板中的foreach foreachelse-----------------
	//在php中分配数组
	$tpl->assign("arr",$array);
	/*
	{foreach}标签的作用是来遍历数组,
	在模板中的书写格式:
	from = $arr		$arr为分配的数组,
	item = ""		为数组值
	key = ""		为数组下标
	name = ""		为该循环的名字,用于访问该循环 key="" 与name=""可省略
	*/
	
	//同 foreach($arr as $key=>$var)
	{foreach from=$arr item="var" key="key" name="Hello"}
		{$key}=>{$var}
	{foreachelse}
		not arr<br>
	{/foreach}
	
	//遍历二维关联数组
	{foreach from=$article item="data"  }
			{$data.article}
			{$data.artId}
	{/foreach}
	
	
	//name的作用为访问foreach循环中的某些变量
	//循环的总次数,循环内外都可使用
	{$smarty.foreach.Hello.total}
	//当前循环执行的次数即行号,循环内使用
	{$smarty.foreach.Hello.iteration}
	//循环的第一次为真,循环内使用
	{$smarty.foreach.Hello.first}
	//循环的最后一次为真,循环内使用
	{$smarty.foreach.Hello.last}
	
	//双重循环写法
	{foreach	from=$arr	item="row"	}
		{foreach	from=$row	item="col"	}
			{$col}
		{/foreach}
	{/foreach}
	//----------------模板中的section遍历数组------------------
	//section优点:效率要比使用foreach高,功能比foreach多
	//section缺点:无法遍历关联数组
	/*section特点:section只能决定循环的次数,遍历数组的方式
	还是去直接访问数组*/
	/*参数:loop="" 要循环的数组; name="Hello"该数组的临时名
	字用于访问该数组; max=""循环的次数;start=""开始遍历的条
	数,step=""每次遍历跳过的步骤*/
	{section loop=$arr name="Hello" max="10" start="5"	step="2"}
		//输出数组全部
		{$arr[Hello]}<br>
		//输出数组的单个值
		{$arr[Hello].id}
		{$arr[Hello].name}
		{$arr[Hello].price}
	{sectionelse}
		not data<br>
	{/section}
	
	/*index索引的功能:每遍历一次数组输出一次索引序号,如果
	设置了step=""的值,则索引的序号的跳步数同step的值*/
	{section loop=$arr name="hello" step="2"}
		//输出的索引序号同遍历所跳的数相同如:1  4  7...
		{$smarty.section.Hello.index}
		//每次遍历数组输出一个数字即行号1  2  3  4...
		//rownum 是iteration的别名
		{$smarty.section.Hello.iteration}
		{$arr[Hello].id}
		{$arr[Hello].name}
		{$arr[Hello].price}<br>
	{/section}
//==============================================================
//---------------------Smarty的缓存技术------------------------
	//Smarty的缓存技术同网页静态化
	/*此段代码放在初始化文件中*/
	//1.开启缓存(开发阶段勿开)
	$tpl->caching=0;	//0表示关闭,1表示开启
	//2.指定缓存文件目录
	$tpl->cache_dir=ROOT."/cache";
	//3.指定缓存的时间
	$tpl->cache_lifetime=60;	//单位秒
	
	/*注意:对于分页结构的网页需要对每个网页进行缓存,
	$tpl->display("模板","缓存id")中的第二个参数为网页缓存
	的id,可根据网页不同的页面有不同的url将缓存id设置为网
	页的url */
	$tpl->display("test.html","cacheId");
	//对整个网站进行缓存
	$tpl->display("test.html",$_SERVER["REQUEST_URI"]);
	
	/*一般情况下,当程序执行到$tpl->display("","")这一步时
	才知道网页是否已经缓存,若没有缓存再执行缓存,但是前
	面的程序已经执行,并没有提高程序的执行效率,所以要在
	未执行前面的程序时首先判断是否已有该网页的缓存。在程
	序执行数据库操作时如果跳过此操作可以节省程序执行时间
	,程序在执行数据库操作时速度最慢*/
	//判断网页对应的cacheId(如Url)网页是否已有缓存
	$tpl->is_cached("test.html","cacheId");
	//先判断模板是否已有缓存,若没有再执行分配数据
	if(!$tpl->is_cached("test.html","cacheId")){
		$tpl->assign("var",$Hello);
	}
	$tpl->display("test.html","cacheId");
	//---------------------局部缓存----------------------------
	/*将php中的分配数据代码$tpl->assign("","")写在判断缓存
	代码if(!is_cached("","")){}的外面,在模板中加入
	{nocache}{/nocache}标签,在此模板中的内容将不会缓存
	但{nocached}标签系统并没有提供,需要自己写*/
	//注册方式写{nocached}块标签
	$tpl->register_block("nocache","ncache");
	//参数:参数,缓存的内容,false(注意:表示经过块的不缓存)
	function ncache($param,$content,false){
		return $content;
	}
	//插件形式加入{nocache}块
	/*1.在 Smarty/libs/plugins 目录下加入block.nocache.php文件,
	在文件中写入内容如下*/
	/*参数:函数的参数(标签属性),缓存内容(标签中的内容),传
	入引用*/
	function smarty_block_nocache($param,$content,&$s){
		return $content;
	}
	//2.将Smarty中的Smarty_Compiler.class.php中的712行改为
	 if($tag_command=="nocache")//判断是nocache块的不缓存
		$this->_plugins['block'][$tag_command] = 
		array($plugin_func, null, null, null, false);
	else
		$this->_plugins['block'][$tag_command] = 
		array($plugin_func, null, null, null, true);
	//-----------------------清除缓存--------------------------
	//清除模板缓存
	$tpl->clear_all_cache();
	//清除某个模板缓存
	$tpl->clear_cache("Hello.html");
	//清除单个缓存
	$tpl->clear_cache("Hello.html","cacheId");
//==============================================================
//--------------------------------------------------------------