打造属于自己的简易缓存系统

提示:本文更新于 6154 天前,技术内容可能已发生变化,仅供参考。

一直以来都在使用smarty的cache功能,但总觉得自己动手打造一个,才更有成就感。网上有很多大神开发的功能完备的缓存系统,不过我打算先从简单的做起,实现动态页面静态化的过程,再逐步完善。这两天我完成了一个较为简易的版本,在此记录一下整个过程。

一、技术要点

本次搭建用到的相关技术关键词包括:PHP、Apache,具体涉及以下技术:

  • mod_rewrite:利用RewriteCondRewriteRule实现地址重写。
  • ob系列函数:用于进行缓冲处理。
  • file_put_contents:这个函数用于生成html文件。

二、运行流程

当用户发出请求url?id=x时,系统会进行如下操作:

  1. 判断文章是否存在

    • 存在:直接转到对应的Html页面。
    • 不存在:通过php读取数据库数据,然后生成html文件,并将其存放到指定目录。

三、实现方法

  1. 地址重写:使用Apache的mod_rewrite模块中的RewriteRule指令来实现重写。
  2. 判断文章是否存在:借助Apache的mod_rewrite模块中的RewriteCond指令进行判断。
  3. 生成html文件

    • 首先通过ob_start()打开缓冲。
    • 接着将读取文章的php文件包含进来。
    • 最后使用file_put_contents将获得的缓冲内容写入指定的HTML文件。

四、代码详解

/Test目录下的.htaccess文件

RewriteEngine On
RewriteRule ^index.html$ /news.php [L]
RewriteCond %{REQUEST_FILENAME}!-s
RewriteRule ^html/news_([0-9]+).html$ getnews.php?id=$1 [L]

其中,第二句RewriteRule ^index.html$ Test/news.php [L]实现了对news.php的访问可通过localhost/Test/index.html达成。

news.php

header("Content-Type:text/html; charset=gbk");//以防出现乱码
mysql_connect("localhost","root","");
mysql_query('SET NAMES gbk');//我的数据库用的gbk编码,请根据自己实际情况调整
mysql_select_db("test");

$sql="SELECT `id`,`title` FROM `arc` order by `id` DESC";
$rs=mysql_query($sql);
while($row=mysql_fetch_array($rs) ){
    echo"<a xhref='/Test/html/news_$row[id].html'>$row[title]</a><br>";
}

此文件的作用是列出文章标题链接。

生成php静态页的过程

当点击链接发出对http://localhost/Test/html/news_3.html的请求时,Apache会通过.htaccess中的第三句:

RewriteCond %{REQUEST_FILENAME}!-s

来判断news_3.html是否存在。RewriteCond表示“定向重写发生条件”,REQUEST_FILENAME是“客户端请求的文件名”,'-s'表示测试指定文件是否存在且是一个尺寸大于0的常规文件,表示匹配条件的反转。所以该句意味着当请求链接不存在时,执行下面的RewriteRule规则。

即当请求的news_3.html不存在时,会重写地址让getnews.php?id=3来处理(若news_3.html存在则直接加载该html文件)。

getnews.php

$id=$_GET['id'];
$root=&$_SERVER['DOCUMENT_ROOT'];
$filename="news_".$id.".html";
$file=$root."/Test/html/".$filename;
ob_start();
include($root."/Test/newsDetail.php");
file_put_contents($file,ob_get_contents());
ob_end_flush();

该文件的功能是判断参数传输的完整性,并调用相应文件生成html文件。

newsDetail.php

header("Content-Type:text/html; charset=gbk");
if( isset($_GET['id']) ){
    $id= &$_GET['id'];
}else{
    header("Location: http://127.0.0.1/lean/Test/html/news_failed.html");
    exit();
}
mysql_connect("localhost","root","");
mysql_query('SET NAMES gbk');
mysql_select_db("test");
$id=$_GET['id'];

$sql="SELECT `news` FROM `arc` WHERE `id`=$id";
$rs=mysql_query($sql);
while($row=mysql_fetch_array($rs) ){
    echo$row['news'];
}

此文件从数据库中读取数据,产生新闻内容,其内容会被getnews.php捕获。

最终,系统会在/Test/html目录下产生以news_文章ID.html命名的html文件。

五、问题与优化

  1. 循环重定向问题:一开始在判断是否存在相应html页面时,采用的是php内置的file_exists()判断,而未使用Apache的RewriteCond。结果导致当news_3.html不存在时,用getnews.php生成news_3.html后,因再次请求触发mod_rewrite,又将news_3.html重写为getnews.php?id=3,形成了死循环。后来将文件存在性的判断交给RewriteCond,指定的html文件不存在时才启用重写规则,成功解决了循环重定向的问题。
  2. 效率优化:起初没有采用ob系列函数,而是使用fopen打开newsDetail.php,再将生成的内容通过fwrite写成html文件,然后用include输出静态页面。在fhjr999的提醒下,改为将newDetail.php包含进getnews.php,通过ob系列函数将生成的内容放入缓冲,然后再生成html文件。经测试,ob的效率约是前者的20倍。

「倘若有所帮助,不妨酌情赞赏!」

Holmesian

感谢您的支持!

使用微信扫描二维码赞赏


相关文章

发表新评论