ThinkPHP 的页面静态化功能的实现(三)

常说的页面静态化分为两种,一种是伪静态,即url 重写,一种是真静态化。

前两篇讲了两种静态化方法,基本都是使用TP自带的静态化机制。但TP写的网站页面路由都比较繁琐复杂,不利于引擎优化。

前段时间做了个网站,由于网站层次太深,在进行SEO优化的时候,不好收录,无奈之下只得自己重新写方法进行页面静态化,采用的方法就是:在后台对每个栏目和内容手动点击进行静态化。后台添加栏目和文章之后手动点击生成静态页面文件。

原理就是:每一个栏目或者内容都唯一的URL路径,根据链接将内容提取出来,然后重新保存文件就是静态化之后的文件。页面中原有的a标签带有的链接,都通过正则表达式匹配之后,重新替换,以保证在一个静态页面中点击链接跳转到的下一个页面也是HTML/目录下的静态化页面。

先将自己写的方法贴出来,参数分别为(栏目或内容的URL路径,静态文件保存路径,生成静态文件的文件名):

function createHtml($url,$dir,$filename){

	$content = file_get_contents($url);                 //获取内容
	
	if (!is_dir($dir)){                                 //如果目录不存在
		mkdir(iconv("UTF-8", "GBK", $dir),0777,true);   //创建目录(777权限)
	}
	
	//-------------------------------------------处理导航链接-------------------------
	$listurls = "/[\'|\"]\/App\/Index\/articalList\/id\/(.*?)[\'|\"]/";
	preg_match_all($listurls,$content,$matchlist);
	foreach ( $matchlist[1] as $key => $value ) {
		$value = trim($value);
		$map['catdir'] = $value;
		$cat = M('cms_cate')->where($map)->limit(1)->find();
		if($cat['lv'] == 1){
			$listurl = "\"/HTML/".$value.".html\"";
		}else if(!empty($cat['pid']) && ($cat['lv'] == 2)){
			$pid = $cat['pid'];
			$tmap['id']=$pid;
			$pcat = M('cms_cate')->where($tmap)->limit(1)->find();
			$pcatdir = $pcat['catdir'];
			$listurl = "\"/HTML/".$pcatdir."/".$value.".html\"";
		}
		
		$content = str_replace ( $matchlist[0][$key], $listurl, $content ); 
	}
	//-----------------------------------------------------------------------------------
	
	
	//------------------------------------处理文章列表页---------------------------------
	//列表页链接进入内容页
	$infourl = "/href=[\'|\"]\/App\/Index\/articalInfo\/id\/(.*?)[\'|\"]/";
	preg_match_all($infourl,$content,$matchlist);
	foreach($matchlist[1] as $key => $value){
		$value = trim($value);
		$map['id'] = $value;
		$cateid = M('Artical')->where($map)->limit(1)->getField('cateid');
		$cat = M('cms_cate')->where('id=' . $cateid)->limit(1)->find();
		if($cat['lv'] == 1){
			$info = "href='/HTML/".$cat['catdir']."/".$value.".html'";
		}else if(!empty($cat['pid']) && ($cat['lv'] == 2)){
			$pid = $cat['pid'];
			$tmap['id']=$pid;
			$pcat = M('cms_cate')->where($tmap)->limit(1)->find();
			$pcatdir = $pcat['catdir'];      
			$info = "href='/HTML/".$pcatdir."/".$cat['catdir']."/".$value.".html'";
		}
		
		$content = str_replace ( $matchlist[0][$key], $info, $content ); 
	}
	
	//文章列表分页
	$page = "//";
	preg_match_all($page,$content,$matchpage);
	foreach ( $matchpage[3] as $key1 => $value1 ) {
		foreach ( $matchpage[1] as $key2 => $value2 ) {
			if($key1 == $key2){
				$value1 = trim($value1);
				$value2 = trim($value2);
				$url = '';
				$content = str_replace ( $matchpage[0][$key1], $url, $content );
			}
		}
	} 
	//-----------------------------------------------------------------------------------
	
	//生成的文件路径与文件名
	$path = $dir."/".$filename.".html";
	if(file_exists($path)){
		unlink($path);                   //删除已有的同名文件
	}
	//'w' 写入方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。  
	$fp = fopen($path, "w");             
	$flag = fwrite($fp, $content);       //写入内容
	fclose($fp);
	
	return $flag;                        //返回写入标识[成功/失败]
}

不同的网站层级结构和路由规则不一样,所以正则匹配规则也就不一样了,大家可以根据自己的网站的路由规则进行灵活调整改动。


在执行之前,当然要在根目录下的程序入口文件index.php中进行如下配置:

define('HTML_PATH', './HTML/');//生成静态页面的文件位置

(1)网站首页静态化

//首页页面静态化
public function setindexhtml(){
	
	$host = I("server.HTTP_HOST");
	
	$url = 'http://'.$host.'/index.php';
	
	$dir = './';               //存放路径
	
	$filename = 'index';       //分类名当文件名
	$res = createHtml($url,$dir,$filename);
	if($res){
		$this->ajaxReturn(array("status"=>"1","msg"=>"操作成功"));
	}else{
		$this->ajaxReturn(array("status"=>"0","msg"=>"操作失败"));
	}
}
将首页静态化之后生成的index.html文件保存在网站的根目录下,在服务器端设置程序入口文件为index.html,如下图:

ThinkPHP 的页面静态化功能的实现(三)_第1张图片
这时候一访问域名,其实就是访问的根目录下的index.html静态文件。而且首页里边a标签跳转到其他页面的链接也都被替换了,点击跳转都会路由到HTML/目录下,寻找对应要跳转的文件名。

(2)文章列表页静态化

//列表页面静态化
public function sethtml(){
	$_G = F('f_data');
	$id =  I("get.id");
	$m = M('cms_cate');
	if (!$id) {
		$info['status'] = 0;
		$info['msg'] = 'ID不能为空!';
		$this->ajaxReturn($info);
	}
	$catdir = trim($id);
	$map['catdir']=$catdir;
	$cat = $m->where($map)->limit(1)->find();
	if (empty($cat)) {
		$info['status'] = 0;
		$info['msg'] = '操作失败,请检查此分类!';
		$this->ajaxReturn($info);
	}
	$psize = $_G['pagesize']['svalue'];          //每个分页展示几条数据
	$tmap['cateid'] = $cat['id'];
	$tmap['status'] = 1;
	if($cat['model'] == 'artical'){
		$count = M('artical')->where($tmap)->count();//当前分类下文章总数
	}else if($cat['model'] == 'product'){
		$count = M('product')->where($tmap)->count();
	}
	$pagecount = ceil(intval($count)/intval($psize));   //分页数(向上取整)
	$host = I("server.HTTP_HOST");
	//多页面,列表分页
	if($pagecount > 1){
		for($i=1;$i<=$pagecount;$i++){
			$url = 'http://'.$host.'/App/Index/articalList/id/'.$catdir.'/p/'.$i.'';
			if($cat['lv'] == 1){
				$dir = './HTML/';  //存放路径
			}else if(!empty($cat['pid']) && ($cat['lv'] == 2)){   //当前类有父级分类
				$pid = $cat['pid'];
				$tmap['id']=$pid;
				$pcat = $m->where($tmap)->limit(1)->find();
				$pcatdir = $pcat['catdir'];
				$dir = './HTML/'.$pcatdir;    //存放路径
			}
			$filename = $catdir.'_'.$i;           //分类名[当前文件名]
			$res = createHtml($url,$dir,$filename);//创建静态文件
			if(!$res){
				$this->ajaxReturn(array("status"=>"0","msg"=>"操作失败"));exit();
			}
		}
	}
	//单页面
	$url = 'http://'.$host.'/App/Index/articalList/id/'.$catdir.'';
	if($cat['lv'] == 1){
		$dir = './HTML/';                //存放路径
	}else if(!empty($cat['pid']) && ($cat['lv'] == 2)){
		$pid = $cat['pid'];
		$tmap['id']=$pid;
		$pcat = $m->where($tmap)->limit(1)->find();
		$pcatdir = $pcat['catdir'];
		$dir = './HTML/'.$pcatdir;      //存放路径
	}
	$filename = $catdir;                    //分类名当文件名
	$res = createHtml($url,$dir,$filename);
	if($res){
		$this->ajaxReturn(array("status"=>"1","msg"=>"静态页面创建成功"));
	}else{
		$this->ajaxReturn(array("status"=>"0","msg"=>"操作失败"));
	}
}
列表页静态化的难点就在于分页,根据不同分页链接中的p参数的不同进行静态化,在判断当前有几个分页之后,如果只有一个页面就生成一个文件,如果有多个就循环执行生成多个文件。如下图:

ThinkPHP 的页面静态化功能的实现(三)_第2张图片

(3)文章内容页面静态化

//内容页面静态化
public function sethtml(){
	$id =  I("get.id");
	if (!$id) {
		$info['status'] = 0;
		$info['msg'] = 'ID不能为空!';
		$this->ajaxReturn($info);
	}
	$map['id'] = $id;
	$cateid = M('Artical')->where($map)->limit(1)->getField('cateid');
	$cat = M('cms_cate')->where('id=' . $cateid)->limit(1)->find();
	if (empty($cat)) {
		$info['status'] = 0;
		$info['msg'] = '操作失败,请检查此分类!';
		$this->ajaxReturn($info);
	}
	if($cat['lv'] == 1){
		$dir = './HTML/'.$cat['catdir'];     //存放路径
	}else if(!empty($cat['pid']) && ($cat['lv'] == 2)){
		$pid = $cat['pid'];
		$tmap['id']=$pid;
		$pcat = M('cms_cate')->where($tmap)->limit(1)->find();
		$pcatdir = $pcat['catdir'];
		$dir = './HTML/'.$pcatdir.'/'.$cat['catdir']; //存放路径
	}
	
	$host = I("server.HTTP_HOST");
	$url = 'http://'.$host.'/App/Index/articalInfo/id/'.$id.'';
	$filename = $id;        //ID当文件名

	$res = createHtml($url,$dir,$filename);
	if($res){
		$this->ajaxReturn(array("status"=>"1","msg"=>"静态页面创建成功"));
	}else{
		$this->ajaxReturn(array("status"=>"0","msg"=>"操作失败"));
	}
}
后台每添加一篇文章,都手动进行静态化一次,就会在HTML/目录下先生成文章所在的分类目录,然后以文章ID为名生成HTML文件。比如某一篇新闻文章id为32,新闻在news栏目下,就会在HTML/news/目录下生成32.html。


(4)一键静态化当前分类下所有文章内容页页面

//一键静态化当前分类下所有文章内容页页面
public function sethtmlall(){
	C('DEFAULT_THEME','App/default/');
	$data = I('get.');
	$cateid = $data['cateid'];
	$map['cateid'] = $cateid;
	$map['status'] = 1;
	$artical = M('Artical')->where($map)->select();
	$cat = M('cms_cate')->where('id=' . $cateid)->limit(1)->find();
	if (empty($cat)) {
		$info['status'] = 0;
		$info['msg'] = '操作失败,请检查此分类!';
		$this->ajaxReturn($info);
	}
	$host = I("server.HTTP_HOST");
	foreach($artical as $key => $value){
		$url = 'http://'.$host.'/App/Index/articalInfo/id/'.$value['id'].'';
		if($cat['lv'] == 1){
			$dir = './HTML/'.$cat['catdir'];                     //存放路径
		}else if(!empty($cat['pid']) && ($cat['lv'] == 2)){
			$pid = $cat['pid'];
			$tmap['id']=$pid;
			$pcat = M('cms_cate')->where($tmap)->limit(1)->find();
			$pcatdir = $pcat['catdir'];
			$dir = './HTML/'.$pcatdir.'/'.$cat['catdir'];        //存放路径
		}
		$filename = $value['id'];
		$res = createHtml($url,$dir,$filename);                  //创建静态文件
		if(!$res){
			$this->ajaxReturn(array("status"=>"0","msg"=>"操作失败"));exit();
		}
	}
	$this->ajaxReturn(array("status"=>"1","msg"=>"静态页面创建成功"));
}
比如新闻栏目下有很多条文章,一条条手动静态化太慢,可以实现一键静态化。先在数据库中查找新闻文章,然后循环遍历进行静态化,就会在HTML/news/目录下生成所有的新闻文章静态页面。如下图:
ThinkPHP 的页面静态化功能的实现(三)_第3张图片

此时再访问网站,访问的全部是静态化的页面,访问的URL也会变为自定义的,简化了网站的层级,便于引擎优化。

静态化案例:

静态化之前:http://www.anumuying.com/index.php

静态化之后:http://www.anumuying.com

不同的网站层级结构和路由规则不一样,所以URL不同,同时正则匹配规则也就不一样了,大家可以根据自己的网站的路由规则进行灵活调整改动。

你可能感兴趣的:(PHP,ThinkPHP)