如果您的网站每天都有数百个访问者众多的页面,您可能希望为您的网站实施某种缓存机制以加快页面加载时间。每个客户端-服务器请求都包含多个数据库查询、服务器响应和处理时间,从而增加了整体页面加载时间。最常见的解决方案是制作称为缓存文件的动态页面的副本并将它们存储在单独的目录中,以后可以将其用作静态页面,而不是一次又一次地重新生成动态页面。
了解动态页面和缓存文件
缓存文件是由动态页面生成的静态副本,这些文件生成一次并存储在单独的文件夹中直到过期,当用户请求内容时,提供相同的静态文件而不是动态生成的页面,从而绕过需要使用服务器端代码一遍又一遍地重新生成 HTML 并从数据库中请求结果。例如,运行多个数据库查询,计算和处理 PHP 代码到 HTML 输出需要几秒钟,增加动态页面的整体页面加载时间,但是缓存文件仅包含纯 HTML 代码,您可以在任何文本编辑器中打开它或浏览器,这意味着它根本不需要处理时间。
动态页面:下图中的示例显示了如何生成动态页面。顾名思义,它是完全动态的,它与数据库对话并根据用户在请求期间提供的不同变量生成 HTML 输出。例如,用户可能想要列出特定作者的所有书籍,它可以通过向数据库发送查询并生成新的 HTML 内容来做到这一点,但每个请求都需要几秒钟的时间来处理,并且使用了特定的服务器内存,这不是如果网站的访问者很少,那就很重要了。但是,考虑到数百名访问者一遍又一遍地从您的网站请求和生成动态页面,这将大大增加压力,从而导致延迟输出和客户端浏览器上的 HTTP 错误。
动态页面示例
缓存文件:- 下图说明了如何提供缓存文件而不是动态页面,如上所述,缓存文件只不过是静态网页。它们包含纯 HTML 代码,缓存页面内容更改的唯一方法是 Web 开发人员手动编辑文件。正如您所见,缓存文件既不需要数据库连接,也不需要处理时间,它是持续降低服务器压力和页面加载时间的理想解决方案。
缓存文件示例
PHP 缓存
使用PHP缓存动态页面还有其他方法,但大家最常用的方法是PHP Output Buffer和Filesystem Functions,将这两种方法结合起来,我们就可以拥有华丽的缓存系统。
PHP 输出缓冲区:它有趣地提高了性能并减少了下载所需的时间,因为输出不是分段发送到浏览器,而是将整个 HTML 页面作为一个变量发送到浏览器。方法非常简单,看看下面的代码:
<?php
ob_start(); // start the output buffer
/* the content */
ob_get_contents(); gets the contents of the output buffer
ob_end_flush(); // Send the output and turn off output buffering
?>
当您在代码顶部调用 ob_start() 时,它会打开输出缓冲,这意味着此后的任何内容都将存储在缓冲区中,而不是在浏览器上输出。可以使用 ob_get_contents() 检索缓冲区中的内容。您应该在代码末尾调用 ob_end_flush() 将输出发送到浏览器并关闭缓冲。
PHP Filesystem :——你可能对PHP文件系统很熟悉,它是PHP核心的一部分,它允许我们读写文件系统。看看下面的代码。
$fp = fopen('/path/to/file.txt', 'w'); //open file for writing
fwrite($fp, 'I want to write this'); //write
fclose($fp); //Close file pointer
你可以看到代码 fopen() 的第一行打开文件进行写入,模式‘w’将文件指针放在文件的开头,如果文件不存在,它会尝试创建一个。第二行 fwrite() 将字符串写入打开的文件,最后 fclose() 在代码开头关闭成功打开的文件。
实现 PHP 缓存
现在你应该很清楚 PHP 输出缓冲区和文件系统了,我们可以使用这两种方法来创建我们的 PHP 缓存系统。请看下图,流程图为我们提供了缓存系统的基本概念。
php缓存系统
循环从用户请求内容开始,我们只检查当前请求的页面是否存在缓存副本,如果不存在则生成新页面,创建缓存副本然后输出结果。如果缓存已经存在,我们只需要获取文件并将其发送到用户浏览器。
查看下面的完整 PHP 缓存代码,您可以将其复制并粘贴到您的 PHP 项目中,它应该可以完美地工作,如上图所示。您可以在代码中进行设置,修改缓存过期时间、缓存文件扩展名、忽略页面等。
<?php
//settings
$cache_ext = '.html'; //file extension
$cache_time = 3600; //Cache file expires afere these seconds (1 hour = 3600 sec)
$cache_folder = 'cache/'; //folder to store Cache files
$ignore_pages = array('', '');
$dynamic_url = 'http://'.$_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . $_SERVER['QUERY_STRING']; // requested dynamic page (full url)
$cache_file = $cache_folder.md5($dynamic_url).$cache_ext; // construct a cache file
$ignore = (in_array($dynamic_url,$ignore_pages))?true:false; //check if url is in ignore list
if (!$ignore && file_exists($cache_file) && time() - $cache_time < filemtime($cache_file)) { //check Cache exist and it's not expired.
ob_start('ob_gzhandler'); //Turn on output buffering, "ob_gzhandler" for the compressed page with gzip.
readfile($cache_file); //read Cache file
echo '<!-- cached page - '.date('l jS \of F Y h:i:s A', filemtime($cache_file)).', Page : '.$dynamic_url.' -->';
ob_end_flush(); //Flush and turn off output buffering
exit(); //no need to proceed further, exit the flow.
}
//Turn on output buffering with gzip compression.
ob_start('ob_gzhandler');
######## Your Website Content Starts Below #########
?>
<!DOCTYPE html>
<html>
<head>
<title>Page to Cache</title>
</head>
<body>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer ut tellus libero.
</body>
</html>
<?php
######## Your Website Content Ends here #########
if (!is_dir($cache_folder)) { //create a new folder if we need to
mkdir($cache_folder);
}
if(!$ignore){
$fp = fopen($cache_file, 'w'); //open file for writing
fwrite($fp, ob_get_contents()); //write contents of the output buffer in Cache file
fclose($fp); //Close file pointer
}
ob_end_flush(); //Flush and turn off output buffering
?>
您必须将您的 PHP 内容放在附上的注释行之间,事实上我建议将它们放在单独的页眉和页脚文件中,以便它可以为所有不同的动态页面生成和提供缓存文件。如果您仔细阅读代码中的注释行,您应该会发现它几乎不言自明。