php缓存机制的一个讲解

再说php缓存机制之前,想来说一下smarty的一个缓存小结,

我们可以随便打开一个缓存文件看一下:

这个说一下缓存集合的一个用法

组名:finance

地址:beijing

姓名:phm

大家注意到没有,缓存文件是不是里面就是已经处理好的代码,他不像编译文件,是Phphtml代码的一个结合体。也就是说这个缓存文件,我们是可以直接拿来就使用的。而它的一个生成原理是什么呢,往下走。

这里先来说一下,用户访问一个php页面的时候,后面发生了什么。

当用户访问php页面的时候,会向apache服务器发出一个请求。而apache不认php文件里面的东西,Apache说,它只认识html,只会解析返回这个html文件。

ok,那么这个时候,它就会找它的小弟来帮忙,这个小弟就是phpapache这个大哥对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返回结果给apcheapache返回结果给用户的浏览器的时候,信息也不会说就一下即时输出,必须要刷新才可以输出。当然,它的这片缓存空间也是有它的大小的。

str_repeat(“需要重复的字符串”,“字符串的重复次数”);返回重复后的字符串。

下面我来说下,php的缓存是有开关控制的,也就是你可以让它关闭,也可以让它开启,默认的情况下是关闭的。

下面第一种对它设置的方法,在php.ini中:

找到output_buffering = 4096

这个时候上面就是打开缓存。我们可以把它设置成为off,然后就关闭了这个缓存。

下面是在页面中进行设置

使用函数ob_start()开启缓存。

下面我们看一下下面的代码会如何输出,

for($i=0;$i<=5;$i++)

{

echo $i."
";

sleep(1);

}

你可能一开始会认为像c/c++那样,隔一秒输出一下信息。隔一秒输出一下信息。但是,这里并不是,而是一下只输出全部的信息。这个就是缓存造成的结果。

好,下面我们呢关闭php缓存,还要刷新浏览器缓存,然后才可以实现数据的即时输出。

for($i=0;$i<=5;$i++)

{

echo $i."
";

ob_flush();//这里是刷新php缓冲区

flush();//这里是刷新浏览器缓冲区

sleep(1);

}

上面基本上就可以实现每一个数据即时输出了。但是,火狐浏览器好像不是很支持fflush这个函数,那么我们就必须填满安的浏览器缓冲区然后输出。

echo str_repeat(" ",4096);

for($i=0;$i<=5;$i++)

{

echo $i."
";

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."
";

}

$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(这里是用来说明这是怎样一个顾虑器)”,”这里是过滤器需要执行的方法”)

下面我们写一个前置过滤器,把编译文件保留下来的注释全部删除。我们随便写一个文件,看看原来编译文件是什么样子。

下面是模板文件当中的代码

{$name}

上面我们从php页面传了一个名字过去。然后经过编译,我们看看编译文件是什么样子。

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");

上面做了一个前置过滤器,然后注册了一下,下面看看重新编译后的文件是什么样子的代码:

 

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}

{$p1->salary()}

而且属性与方法的访问都不会做任何的限制。

下面看一下注册对象的访问。在此之前,先来给大家说一下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}

问:如果想在模板文件中,给某个方法传入参数并且显示,怎么来处理

 

public function salary($arg)

{

//直接把这个信息给返回

return $arg['name']."||".$arg['age'];

}

可以把方法参数做如上面的一个处理,而此时这个方法的参数就是一个数组信息。它的键就是在模板中传递的变量信息,下面来看看模板中的代码:

{p1->salary name="张三" age="23"}

上面方法就会接收模板传过来的数据,并且用一个数组形式保存,然后打印,注意模板文件中的变量是不加$符号的。

你可能感兴趣的:(smarty模板技术)