php页面静态化,是把那些内容不常变化的页面静态化,而不通过动态程从数据库或者缓存中读出,以此来增加响应速度和减轻服务器压力。这里的要点是对不常变化的内容做静态化,如:新闻,博客等。而经常变化的内容,如微博,就不适合做静态化。还有一些页面,大部分是不变内容,但部分是经常变动的内容,如新闻页包含有最新评论,这样的页面,也可以做静态化,只是需要对经常变动的部分做动态处理。
php页面静态化实现,主要有两个方面的问题要处理,第一是怎么样生成静态化文件,第二是怎么样更新静态文件。
一、 静态页面生成
静态页面生成,主要的方式是通过php的 output buffer系列函数来实现。output buffer(这里简称ob)是php的输出缓冲,在php输出时,先要写入到这个缓冲区,只有当php程序结束或者缓冲区写满的时候,才会输出到浏览器。基于这个特性,我们的思路是,执行php动态程序生成页面,通过ob系列函数,如ob_get_contents()获得缓冲区中的页面内容,然后用文件操作函数如 file_put_content(), 将页面保存到文件中。
//开启output buffer 缓冲区,如果php已经开启,则不需要。
// php.ini 中,output_buffering = 4096
if(!ini_get('output_buffering')){
ob_start();
}
//从数据库或缓存中获取数据,本行是伪代码,get_from_stroge需要具体实现。
$data = get_from_stroge();
//调用模板组织成页面
require "templates/index.php";
//获取缓冲区中的页面,并清除缓冲区
$content = ob_get_clean();
//将页面保存成为静态文件
file_put_contents("index.htm",$content);
index.htm就生成了,在浏览器中打入static.lukexp.com/index.htm 就能打开直接访问生成的静态页面,static.lukexp.com是我本地的虚拟域名,可以通过修改hosts文件和apache虚拟站点来实现。
上文提到有些页面大部分是不变内容,小部分是即时更新的内容,类似的页面,我们可以做局部动态。举个例子,一篇博文和博文的评论,博文是基本不变内容,评论是经常要变动的动态内容。这个时候,我们就要用到局部动态了。主要的思路是通过ajax异步加载动态内容。
<html>
<head></head>
<body>
<div class="blogcontent">
//博文内容
</div>
<div id="blogcomment" data-id="1"></div>
<script type="text/javascript" src="st/js/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
var blogid = $(this).attr("data-id");
$.post("getComment.php",{id:blogid},function(RES){
if(RES.code = 0){
$("#blogcomment").html(RES.data.contentHtml);
}
},'json');
});
</script>
</body>
</html>
这个页面就是生成的博文静态页面,其中的评论是空的<div id="blogcomment"></div>,页面中使用了jquery提供的ajax方法,向后台访问getComment.php来动态获取评论内容。然后后显示在评论区域中。后台getComment.php的大致代码如下:
//***************** getComment.php ************************
if(ini_get('output_buffering')!==false){
ob_start();
}
$blog_id = $_GET['id'];
$commentData = get_comment_data($blog_id);
require_once("template/comment.php");
$content = ob_get_clean();
$result = array('code'=>0,'msg'=>'',data=>array('contentHtml'=>$content));
echo json_encode($result);
我们说的内容不变的页面生成静态页面,但这里的不变也是相对的,比如,博文做了编辑,这个时候,静态页面也要做更新了。更新通常有四种方式:主动触发,过期重建,定时更新,还有被动生成。
1、主动触发的方式,例如上文说的博文做了编辑,这个时候,我们可以在博文保存的时候,同步生成新的博文静态页面。也可以专门提供一个按钮,让用户手动触发重新生成静态页面的操作。
2、过期重建方式,生成的时候对静态页面的时间做一个判断,超过了一定的时间,则重新生成。如:
if(!file_exists("index.htm") || time()-filemtime("index.htm")>300){
if(ini_get('output_buffering')!==false){
ob_start();
}
$data = get_from_stroge();
require "templates/index.php";
$content = ob_get_clean();
file_put_contents("index.htm",$content);
}
3、定期更新。定时更新是使用windows的计划任务或者linux的cronjob 之类的工具,定时执行脚本来更新静态页面。以cronjob为例
sudo crontab -e
1 * * * * php /var/www/static.lukexp.com/update.php
/etc/init.d/cron reload
以上命令的意思是,每隔1分钟,执行/var/www/static.lukexp.com/update.php,这里update.php就是生成静态页面的代码。
4、被动生成方式。是指在访问到某个页面的时候,如果该页面已经存在则正常访问,否则就生成静态页面并显示。这个过程中,需要用的URL Rewrite即伪静态。例如,上文中博文的静态页面的URL是static.lukexp.com/blog/1.htm,而对应的动态url 是static.lukexp.com/index.php?act=blog&id=1。
以apache为例,首先,我们要开启apache的 rewrite模块,在httd.conf中,去掉 LoadModule rewrite_module modules/mod_rewrite.so 前的“#”,并在 虚拟站点配置中添加rewrite规则,
<VirtualHost *:80>
DocumentRoot /var/www/static.lukexp.com/public
ServerName static.lukexp.com
<Directory '/var/www/static.lukexp.com/public'>
Options FollowSymLinks
AllowOverride None
Order Deny,Allow
Allow from all
</Directory>
RewriteEngine on
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule ^/(\w+)/(\d+).htm$ /index.php?act=$1&id=$2
</VirtualHost>
以上的意思就是,/blog/1.htm不存在的时候,就访问index.php?act=blog&id=1,而index.php则根据根据参数调用数据并生成静态页面,然后显示,代码如下:
$act = $_GET['act'];
$id = $_GET['id'];
if(ini_get('output_buffering')!==false){
ob_start();
}
//从数据库或缓存中获取数据,本行是伪代码,get_from_stroge需要具体实现。
//$data = get_from_stroge($act,$id);
//调用模板组织成页面
require "templates/{$act}.php";
//获取缓冲区中的页面,但不清除缓冲区
$content = ob_get_contents();
//将页面保存成为静态文件
$stfile = "{$act}/{$id}.htm";
file_put_contents($stfile,$content);
在我们实际应用的过程中,以上几种静态文件的生成和更新方式,要根据实际需求,挑选其中一种或者综合几种方式来实现。一般不会单独出现。例如上例中,我们也可以直接到index.php,然后在index.php中根据时间来判断模板是否过期,如果不过期则加载静态文件,否则重新生成。总之,还是要具体的业务需求来挑选实现方式。