再说php缓存机制之前,想来说一下smarty的一个缓存小结,
我们可以随便打开一个缓存文件看一下:
<body>
<h2>这个说一下缓存集合的一个用法</h2>
组名:finance
地址:beijing
姓名:phm
</body>
</html><?php }} ?>
大家注意到没有,缓存文件是不是里面就是已经处理好的代码,他不像编译文件,是Php与html代码的一个结合体。也就是说这个缓存文件,我们是可以直接拿来就使用的。而它的一个生成原理是什么呢,往下走。
这里先来说一下,用户访问一个php页面的时候,后面发生了什么。
当用户访问php页面的时候,会向apache服务器发出一个请求。而apache不认php文件里面的东西,Apache说,它只认识html,只会解析返回这个html文件。
ok,那么这个时候,它就会找它的小弟来帮忙,这个小弟就是php,apache这个大哥对php说,php,你给老子解析一下这个文件,然后返回一个html的文件代码过来,我好返回给用户看,不然用户走了,没钱赚了。
ok ,那么这个时候,Php接到老大的命令,就说,好,大哥,我给你解析一下。这个时候,我们就要进入到php的缓存机制里面。
上面的用户请求路线就是下面这种形式:
用户->apache->php
ok,我们现在已经找到php,那么我们就来分析一下,看看下面的代码:
再看代码之前,先来看几个函数:
u ob_get_clean()这个就是卸磨杀驴的一个做法,我们把缓冲区里面的内容已经得到了,得到之后,我们在删除缓冲区的内容,也就是这个函数执行完毕之后,缓冲区的内容就没有了。
u ob_clean()清空缓冲区的内容,不会得到缓冲区的内容
u sleep()以秒为单位的,让这个程序暂停一下的时间。在linuxc中就是这个函数原型
u ob_get_contents()只会得到缓冲区的内容,但是不删除删除缓冲区的内容。
u ob_flush();//这个是刷新php缓冲区文件的内容。因为缓冲区有一个原理就是说,当缓冲区没有被填满的时候,那么缓冲区是不会把内容输出的,只有就是说,当缓冲区内容被填满的时候,才会被输出。那么这个时候,如果我们想即时输出,那么就需要刷新一下缓冲区。
u ob_start();
打开输出控制缓冲,当php页面的缓存机制没有打开的时候,就可以用这个函数暂时打开一下。
u flush()
这个是针对浏览器的一个刷新缓存处理,因为浏览器本身也是自带缓存的,当然,缓存原理更php是一样的,所以,也就是说,当php返回结果给apche,apache返回结果给用户的浏览器的时候,信息也不会说就一下即时输出,必须要刷新才可以输出。当然,它的这片缓存空间也是有它的大小的。
str_repeat(“需要重复的字符串”,“字符串的重复次数”);返回重复后的字符串。
下面我来说下,php的缓存是有开关控制的,也就是你可以让它关闭,也可以让它开启,默认的情况下是关闭的。
下面第一种对它设置的方法,在php.ini中:
找到output_buffering = 4096
这个时候上面就是打开缓存。我们可以把它设置成为off,然后就关闭了这个缓存。
下面是在页面中进行设置
使用函数ob_start()开启缓存。
下面我们看一下下面的代码会如何输出,
for($i=0;$i<=5;$i++)
{
echo $i."<br/>";
sleep(1);
}
你可能一开始会认为像c/c++那样,隔一秒输出一下信息。隔一秒输出一下信息。但是,这里并不是,而是一下只输出全部的信息。这个就是缓存造成的结果。
好,下面我们呢关闭php缓存,还要刷新浏览器缓存,然后才可以实现数据的即时输出。
for($i=0;$i<=5;$i++)
{
echo $i."<br/>";
ob_flush();//这里是刷新php缓冲区
flush();//这里是刷新浏览器缓冲区
sleep(1);
}
上面基本上就可以实现每一个数据即时输出了。但是,火狐浏览器好像不是很支持fflush这个函数,那么我们就必须填满安的浏览器缓冲区然后输出。
echo str_repeat(" ",4096);
for($i=0;$i<=5;$i++)
{
echo $i."<br/>";
ob_flush();//这里是刷新php缓冲区
flush();//这里是刷新浏览器缓冲区
sleep(1);
}
那么,我们怎么得到缓冲区文件的内容呢?是不是可以用到上面的函数ob_get_contents
ob_get_clean,我们得到它,然后读入到一个文件比如.php.html文件里面去。
从缓冲区读内容到一个文件中去。回到我们smarty页面,我们是要去访问.php页面,然后通过.php页面去访问.html页面,一旦访问,缓存里面是不是就会有这样一个已经生成好的文件。只是我们通过一种手法得到了这个文件。
回过头来,看我们下面的代码:
for($i=0;$i<=5;$i++)
{
echo $i."<br/>";
}
$str=ob_get_contents();//上面就会得到缓存区文件的内容
//然后把这个缓存内容放到一个文件中去。
file_put_contents("./test.php.html",$str);
下面我来说一下smarty的执行流程
我们是通过一个php文件->display(“模板文件”)
接下来这个模板文件会去判断是否有缓存文件和是否有编译文件。如果有缓存文件就直接跑缓存文件,如果没有,而是有编译文件,判断一下是否修改了模板文件,如果没有修改,直接使用编译文件。如果上面两个条件都不满足,那么往下走。
这个时候我们会碰到一个前置过滤器(preFilter),他可以帮我们过滤掉模板文件的注释,或者说,缓存文件中本身不需要存在的注释。然后编译模板,在生成编译文件之前,我们又会碰到一个后置过滤器(postFilter)。后置过滤器可以帮助我们比如为每一个编译文件添加一个作者信息,或者公众说明的一个注释。你想啊,一般在程序中,不可能只有一个模板文件,一般是有多个模板文件的,而这个时候,如果手动的去处理每一个模板文件的内容,是不是就会很没有效率。所以我们这里可以用到后置过滤器。
上面处理完了,就会生成结果,然后又会碰上一个输出过滤器,这个过滤器可以让我们把输出内容进行替换一下。如果开启了缓存,输出过滤器的内容也会跑到缓存里面去。
好了下面来说一下三种过滤器的大致用法:
先来说一下前置过滤器的用法:
我们可以通过前置过滤器,把编译文件的注释给删除掉。因为,编译文件我们一般是不去看的,我们一般只看模板文件。
下面先来认识几个函数:
u str_replace(“在字符串中查找的值”,”要替换用的值”,”要执行替换的字符串目标值”)进行一个字符串的一个替换
上面这个函数返回替换后的字符串
u preg_replace(“在字符串中查找的值,这个是一个正则模式匹配”,”用于替换的字符串”,”要执行替换的字符串的目标值”)这个是执行一个正则表达式的搜索与替换。
在smarty里面有一个方法,这个方法是用来注册过滤器的,你只有注册了过滤器,才可以使用,这个方法是这个样子的$smarty->registerFilter(“pre|post|output(这里是用来说明这是怎样一个顾虑器)”,”这里是过滤器需要执行的方法”)。
下面我们写一个前置过滤器,把编译文件保留下来的注释全部删除。我们随便写一个文件,看看原来编译文件是什么样子。
下面是模板文件当中的代码
<body>
<!--这是一个注释,编译文件不想要这个注释-->
{$name}
上面我们从php页面传了一个名字过去。然后经过编译,我们看看编译文件是什么样子。
<body>
<!--这是一个注释,编译文件不想要这个注释-->
<?php echo $_smarty_tpl->tpl_vars['name']->value;?>
大家注意到没有,编译文件是不是也存在这个注释呢。好,下面我们写代码,让编译文件没有,而模板文件有注释存在。
下面我们看一下php代码页面的一个处理方法:
include "./MySmarty.class.php";//引入这个类文件
$smarty=new MySmarty();//实例化一个对象
function delete_note($tpl)
{
//这个也就是说把模板当中的注释用正则替换成空内容
$cont=preg_replace("/<!--.*-->/","",$tpl);
return $cont;//上面替换了模板中的内容,然后返回这个替换的内容。
}
//下面我们要调用smarty中的方法,注册一下这个过滤器。
$smarty->registerFilter("pre","delete_note");
$smarty->assign('name',"蒲向鑫");
//下面展示一下这个模板
$smarty->display("10.html");
上面做了一个前置过滤器,然后注册了一下,下面看看重新编译后的文件是什么样子的代码:
<body>
<?php echo $_smarty_tpl->tpl_vars['name']->value;?>
上面这个时候,是不是就没有注释了,这个就是前置过滤器的一个使用。
下面我们来说一下后置过滤器的使用,在程序处理成为编译文件之前,会经过一个后置过滤器的一个处理,我们这里就用后置过滤器,为这个模板文件添加一些开发相关的信息。
下面是php页面的代码:
include "./MySmarty.class.php";
$smarty=new MySmarty();//实例化一个对象
function insert_note($tpl)
{
//为这个模板增加注释,准确的说,是为每一个使用这个页面的模板增加注释。
return "<!--作者:张三-->".$tpl;
}
//下面我们要注册一下这个过滤器
$smarty->registerFilter("post","insert_note");
$smarty->assign('name',"张三");
$smarty->display("11.html");
注意,在执行之前,如果有编译文件存在,记得删除编译文件重新编译。下面编译文件就没有问题了,里面就会多添加一条上面那样的注释。
下面我们再来说明一下输出过滤器的使用。输出过滤器,编译文件已经生成了。这个时候的过滤器,它是在缓存文件之前进行处理的一个过滤器。下面我们用输出过滤器来让文件内容有一个替换效果,下面是php页面的代码:
include "./MySmarty.class.php";
$smarty1=new MySmarty();
function change_note($tpl)
{
//输出过滤器的内容可以跑到缓存文件里面,但是不会跑到编译文件里面
//就是进行一个字符串替换就可以了
return str_replace("张三","这个世界",$tpl);
}
//下面来注册一下这个输出过滤器
$smarty1->registerFilter("output","change_note");
$smarty1->assign('name',"张三");
上面就会把模板文件当中有的张三进行一个替换输出。它不会改变模板文件与编译文件本身原有的内容。只会,对缓存文件的内容直接作出改变。
这里插入一个小的知识点,如果我们不想每次修改了比如php页面,我们又要把之前的编译文件删除,重新编译来看结果的话,我们可以调用smarty的一个方法clearCompiledTemplate(“模板文件名字”,调用了这个方法,每次执行php文件,就会把模板文件重新编译一下。也就是说强制重新编译模板文件。
下面我们来说一下数据对象
数据对象其实就是一个盒子,盒子里面保存的数据,在必要的时候把这个盒子扔给某一个模板然后再来使用。
我们一个网站首页面,版面是不是非常的多呢。我们不可以一个页面,就只用到了一个模板对不对。一个页面应该是用到了很多的模板才对。那么这里多个模板可能是多个人开发的,这里就会存在一个问题。当我们在主php页面进行数据传递的时候,是不是会遇到多个不同的模板使用相同的变量的问题。那么这个时候,我们怎么知道这两个变量,该是什么模板来使用呢。
下面看一下代码:比如我们做四个不同的页面。页面的名字以具体开发中的名字为准。
head.html这个是头模板页面
demo1.html这个是主体页面1
demo2.html这个是主体页面2
foot.html这个是脚部页面。
下面是php页面的代码:
//$smarty->assign(“name”,”张三”);
//$smarty-assign(“name”,”李四”);
//你说上面这个两个变量分别应该交给什么模板使用,所以我们应该创建数据对象
$one=$smarty->createData();//创建一个数据对象,箱子
//然后抛出这个箱子
$one->assign(“name”,”张三”)//这里就把箱子给跑出去了,谁来接收呢?,那就是模板
$smarty->display(‘head.html”);
$smarty->display(“demo1.html”,$one);这个数据对象demo1.html模板接收。
$smarty->display(“demo2.html”);
$smarty->display(“demo3.html”);
当然了,我们可以封装很多的数据对象,往一个模板里面抛。
下面来说一下对象注册。
我们都知道smarty是可以传对象到模板中使用的。
在模板中是不是有属性与方法呢,而对象注册研究的就是对象的方法,我们可以对对象当中的某一个方法做具体的限制。让模板不能去访问。
当我们正常传入一个对象的时候,在模板文件中,是如下访问的:
{$p1->name}<br/>
{$p1->salary()}<br/>
而且属性与方法的访问都不会做任何的限制。
下面看一下注册对象的访问。在此之前,先来给大家说一下smarty中的一个注册对象方法$smarty->registerObject(“传递到模板的变量名”,”具体的对象”,array(“这个里面是方法,存在这个数组里面的方法才可以使用”))
下面是注册对象的php代码:
include "./MySmarty.class.php";
class information{
public $name="高新区软件园";
public function salary()
{
//这是一个返回工资的方法
return "5000";
}
public function money()
{
//这个是返回总的余额个数
return "20000";
}
}
$p1=new information();
$smarty=new MySmarty();
$smarty->registerObject("p1",$p1,array("money"));
$smarty->display("13.html");
我们只给了money方法可以在模板中调用。
下面看一下在模板中如何调用这个方法,与直接传对象调用是不一样的。这个调用,变量名不加$,方法不加花括号
body>
{p1->money}<br/>
问:如果想在模板文件中,给某个方法传入参数并且显示,怎么来处理
public function salary($arg)
{
//直接把这个信息给返回
return $arg['name']."||".$arg['age'];
}
可以把方法参数做如上面的一个处理,而此时这个方法的参数就是一个数组信息。它的键就是在模板中传递的变量信息,下面来看看模板中的代码:
{p1->salary name="张三" age="23"}<br/>
上面方法就会接收模板传过来的数据,并且用一个数组形式保存,然后打印,注意模板文件中的变量是不加$符号的。