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

来源:互联网 发布:手动安装windows补丁 编辑:程序博客网 时间:2024/04/27 08:22

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

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

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

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

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

[php] view plain copy
  1. function createHtml($url,$dir,$filename){  
  2.   
  3.     $content = file_get_contents($url);                 //获取内容  
  4.       
  5.     if (!is_dir($dir)){                                 //如果目录不存在  
  6.         mkdir(iconv("UTF-8""GBK"$dir),0777,true);   //创建目录(777权限)  
  7.     }  
  8.       
  9.     //-------------------------------------------处理导航链接-------------------------  
  10.     $listurls = "/[\'|\"]\/App\/Index\/articalList\/id\/(.*?)[\'|\"]/";  
  11.     preg_match_all($listurls,$content,$matchlist);  
  12.     foreach ( $matchlist[1] as $key => $value ) {  
  13.         $value = trim($value);  
  14.         $map['catdir'] = $value;  
  15.         $cat = M('cms_cate')->where($map)->limit(1)->find();  
  16.         if($cat['lv'] == 1){  
  17.             $listurl = "\"/HTML/".$value.".html\"";  
  18.         }else if(!empty($cat['pid']) && ($cat['lv'] == 2)){  
  19.             $pid = $cat['pid'];  
  20.             $tmap['id']=$pid;  
  21.             $pcat = M('cms_cate')->where($tmap)->limit(1)->find();  
  22.             $pcatdir = $pcat['catdir'];  
  23.             $listurl = "\"/HTML/".$pcatdir."/".$value.".html\"";  
  24.         }  
  25.           
  26.         $content = str_replace ( $matchlist[0][$key], $listurl$content );   
  27.     }  
  28.     //-----------------------------------------------------------------------------------  
  29.       
  30.       
  31.     //------------------------------------处理文章列表页---------------------------------  
  32.     //列表页链接进入内容页  
  33.     $infourl = "/href=[\'|\"]\/App\/Index\/articalInfo\/id\/(.*?)[\'|\"]/";  
  34.     preg_match_all($infourl,$content,$matchlist);  
  35.     foreach($matchlist[1] as $key => $value){  
  36.         $value = trim($value);  
  37.         $map['id'] = $value;  
  38.         $cateid = M('Artical')->where($map)->limit(1)->getField('cateid');  
  39.         $cat = M('cms_cate')->where('id=' . $cateid)->limit(1)->find();  
  40.         if($cat['lv'] == 1){  
  41.             $info = "href='/HTML/".$cat['catdir']."/".$value.".html'";  
  42.         }else if(!empty($cat['pid']) && ($cat['lv'] == 2)){  
  43.             $pid = $cat['pid'];  
  44.             $tmap['id']=$pid;  
  45.             $pcat = M('cms_cate')->where($tmap)->limit(1)->find();  
  46.             $pcatdir = $pcat['catdir'];        
  47.             $info = "href='/HTML/".$pcatdir."/".$cat['catdir']."/".$value.".html'";  
  48.         }  
  49.           
  50.         $content = str_replace ( $matchlist[0][$key], $info$content );   
  51.     }  
  52.       
  53.     //文章列表分页  
  54.     $page = "/<a (.*?) href=[\'|\"]\/Index\/articalList\/id\/(.*?)\/p\/(.*?)[\'|\"]>/";  
  55.     preg_match_all($page,$content,$matchpage);  
  56.     foreach ( $matchpage[3] as $key1 => $value1 ) {  
  57.         foreach ( $matchpage[1] as $key2 => $value2 ) {  
  58.             if($key1 == $key2){  
  59.                 $value1 = trim($value1);  
  60.                 $value2 = trim($value2);  
  61.                 $url = '<a '.$value2.' href="/HTML/'.$matchpage[2][0].'_'.$value1.'.html">';  
  62.                 $content = str_replace ( $matchpage[0][$key1], $url$content );  
  63.             }  
  64.         }  
  65.     }   
  66.     //-----------------------------------------------------------------------------------  
  67.       
  68.     //生成的文件路径与文件名  
  69.     $path = $dir."/".$filename.".html";  
  70.     if(file_exists($path)){  
  71.         unlink($path);                   //删除已有的同名文件  
  72.     }  
  73.     //'w' 写入方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。    
  74.     $fp = fopen($path"w");               
  75.     $flag = fwrite($fp$content);       //写入内容  
  76.     fclose($fp);  
  77.       
  78.     return $flag;                        //返回写入标识[成功/失败]  
  79. }  

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


在执行之前,当然要在根目录下的程序入口文件index.php中进行如下配置:
[php] view plain copy
  1. define('HTML_PATH''./HTML/');//生成静态页面的文件位置  

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


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

(2)文章列表页静态化

[php] view plain copy
  1. //列表页面静态化  
  2. public function sethtml(){  
  3.     $_G = F('f_data');  
  4.     $id =  I("get.id");  
  5.     $m = M('cms_cate');  
  6.     if (!$id) {  
  7.         $info['status'] = 0;  
  8.         $info['msg'] = 'ID不能为空!';  
  9.         $this->ajaxReturn($info);  
  10.     }  
  11.     $catdir = trim($id);  
  12.     $map['catdir']=$catdir;  
  13.     $cat = $m->where($map)->limit(1)->find();  
  14.     if (empty($cat)) {  
  15.         $info['status'] = 0;  
  16.         $info['msg'] = '操作失败,请检查此分类!';  
  17.         $this->ajaxReturn($info);  
  18.     }  
  19.     $psize = $_G['pagesize']['svalue'];          //每个分页展示几条数据  
  20.     $tmap['cateid'] = $cat['id'];  
  21.     $tmap['status'] = 1;  
  22.     if($cat['model'] == 'artical'){  
  23.         $count = M('artical')->where($tmap)->count();//当前分类下文章总数  
  24.     }else if($cat['model'] == 'product'){  
  25.         $count = M('product')->where($tmap)->count();  
  26.     }  
  27.     $pagecount = ceil(intval($count)/intval($psize));   //分页数(向上取整)  
  28.     $host = I("server.HTTP_HOST");  
  29.     //多页面,列表分页  
  30.     if($pagecount > 1){  
  31.         for($i=1;$i<=$pagecount;$i++){  
  32.             $url = 'http://'.$host.'/App/Index/articalList/id/'.$catdir.'/p/'.$i.'';  
  33.             if($cat['lv'] == 1){  
  34.                 $dir = './HTML/';  //存放路径  
  35.             }else if(!empty($cat['pid']) && ($cat['lv'] == 2)){   //当前类有父级分类  
  36.                 $pid = $cat['pid'];  
  37.                 $tmap['id']=$pid;  
  38.                 $pcat = $m->where($tmap)->limit(1)->find();  
  39.                 $pcatdir = $pcat['catdir'];  
  40.                 $dir = './HTML/'.$pcatdir;    //存放路径  
  41.             }  
  42.             $filename = $catdir.'_'.$i;           //分类名[当前文件名]  
  43.             $res = createHtml($url,$dir,$filename);//创建静态文件  
  44.             if(!$res){  
  45.                 $this->ajaxReturn(array("status"=>"0","msg"=>"操作失败"));exit();  
  46.             }  
  47.         }  
  48.     }  
  49.     //单页面  
  50.     $url = 'http://'.$host.'/App/Index/articalList/id/'.$catdir.'';  
  51.     if($cat['lv'] == 1){  
  52.         $dir = './HTML/';                //存放路径  
  53.     }else if(!empty($cat['pid']) && ($cat['lv'] == 2)){  
  54.         $pid = $cat['pid'];  
  55.         $tmap['id']=$pid;  
  56.         $pcat = $m->where($tmap)->limit(1)->find();  
  57.         $pcatdir = $pcat['catdir'];  
  58.         $dir = './HTML/'.$pcatdir;      //存放路径  
  59.     }  
  60.     $filename = $catdir;                    //分类名当文件名  
  61.     $res = createHtml($url,$dir,$filename);  
  62.     if($res){  
  63.         $this->ajaxReturn(array("status"=>"1","msg"=>"静态页面创建成功"));  
  64.     }else{  
  65.         $this->ajaxReturn(array("status"=>"0","msg"=>"操作失败"));  
  66.     }  
  67. }  
列表页静态化的难点就在于分页,根据不同分页链接中的p参数的不同进行静态化,在判断当前有几个分页之后,如果只有一个页面就生成一个文件,如果有多个就循环执行生成多个文件。如下图:


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

[php] view plain copy
  1. //内容页面静态化  
  2. public function sethtml(){  
  3.     $id =  I("get.id");  
  4.     if (!$id) {  
  5.         $info['status'] = 0;  
  6.         $info['msg'] = 'ID不能为空!';  
  7.         $this->ajaxReturn($info);  
  8.     }  
  9.     $map['id'] = $id;  
  10.     $cateid = M('Artical')->where($map)->limit(1)->getField('cateid');  
  11.     $cat = M('cms_cate')->where('id=' . $cateid)->limit(1)->find();  
  12.     if (empty($cat)) {  
  13.         $info['status'] = 0;  
  14.         $info['msg'] = '操作失败,请检查此分类!';  
  15.         $this->ajaxReturn($info);  
  16.     }  
  17.     if($cat['lv'] == 1){  
  18.         $dir = './HTML/'.$cat['catdir'];     //存放路径  
  19.     }else if(!empty($cat['pid']) && ($cat['lv'] == 2)){  
  20.         $pid = $cat['pid'];  
  21.         $tmap['id']=$pid;  
  22.         $pcat = M('cms_cate')->where($tmap)->limit(1)->find();  
  23.         $pcatdir = $pcat['catdir'];  
  24.         $dir = './HTML/'.$pcatdir.'/'.$cat['catdir']; //存放路径  
  25.     }  
  26.       
  27.     $host = I("server.HTTP_HOST");  
  28.     $url = 'http://'.$host.'/App/Index/articalInfo/id/'.$id.'';  
  29.     $filename = $id;        //ID当文件名  
  30.   
  31.     $res = createHtml($url,$dir,$filename);  
  32.     if($res){  
  33.         $this->ajaxReturn(array("status"=>"1","msg"=>"静态页面创建成功"));  
  34.     }else{  
  35.         $this->ajaxReturn(array("status"=>"0","msg"=>"操作失败"));  
  36.     }  
  37. }  
后台每添加一篇文章,都手动进行静态化一次,就会在HTML/目录下先生成文章所在的分类目录,然后以文章ID为名生成HTML文件。比如某一篇新闻文章id为32,新闻在news栏目下,就会在HTML/news/目录下生成32.html。


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

[php] view plain copy
  1. //一键静态化当前分类下所有文章内容页页面  
  2. public function sethtmlall(){  
  3.     C('DEFAULT_THEME','App/default/');  
  4.     $data = I('get.');  
  5.     $cateid = $data['cateid'];  
  6.     $map['cateid'] = $cateid;  
  7.     $map['status'] = 1;  
  8.     $artical = M('Artical')->where($map)->select();  
  9.     $cat = M('cms_cate')->where('id=' . $cateid)->limit(1)->find();  
  10.     if (empty($cat)) {  
  11.         $info['status'] = 0;  
  12.         $info['msg'] = '操作失败,请检查此分类!';  
  13.         $this->ajaxReturn($info);  
  14.     }  
  15.     $host = I("server.HTTP_HOST");  
  16.     foreach($artical as $key => $value){  
  17.         $url = 'http://'.$host.'/App/Index/articalInfo/id/'.$value['id'].'';  
  18.         if($cat['lv'] == 1){  
  19.             $dir = './HTML/'.$cat['catdir'];                     //存放路径  
  20.         }else if(!empty($cat['pid']) && ($cat['lv'] == 2)){  
  21.             $pid = $cat['pid'];  
  22.             $tmap['id']=$pid;  
  23.             $pcat = M('cms_cate')->where($tmap)->limit(1)->find();  
  24.             $pcatdir = $pcat['catdir'];  
  25.             $dir = './HTML/'.$pcatdir.'/'.$cat['catdir'];        //存放路径  
  26.         }  
  27.         $filename = $value['id'];  
  28.         $res = createHtml($url,$dir,$filename);                  //创建静态文件  
  29.         if(!$res){  
  30.             $this->ajaxReturn(array("status"=>"0","msg"=>"操作失败"));exit();  
  31.         }  
  32.     }  
  33.     $this->ajaxReturn(array("status"=>"1","msg"=>"静态页面创建成功"));  
  34. }  
比如新闻栏目下有很多条文章,一条条手动静态化太慢,可以实现一键静态化。先在数据库中查找新闻文章,然后循环遍历进行静态化,就会在HTML/news/目录下生成所有的新闻文章静态页面。如下图:

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

静态化案例:

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

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

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

原创粉丝点击