本文目录导读:

在 PHP 中,缓存控制主要涉及 浏览器端缓存(通过 HTTP 头)和 服务端缓存(如 Opcode、数据缓存)两个方面,下面从这三个维度详细说明。
浏览器端缓存控制(HTTP 头)
通过设置 header() 函数控制浏览器或代理如何缓存页面。
禁止缓存(动态页面常用)
header("Cache-Control: no-cache, no-store, must-revalidate"); // HTTP/1.1
header("Pragma: no-cache"); // HTTP/1.0
header("Expires: 0"); // 设置过期时间为过去
允许缓存,但需验证
// 缓存30秒,之后必须向服务器验证是否修改
header("Cache-Control: private, max-age=30, must-revalidate");
设置强缓存(静态资源常用)
// 缓存1年(31536000秒)
$expires = 60 * 60 * 24 * 365;
header("Cache-Control: public, max-age=" . $expires);
header("Expires: " . gmdate("D, d M Y H:i:s", time() + $expires) . " GMT");
ETag + Last-Modified 配合 304 状态码
$lastModified = filemtime(__FILE__);
$etag = md5_file(__FILE__);
header("Last-Modified: " . gmdate("D, d M Y H:i:s", $lastModified) . " GMT");
header("ETag: \"$etag\"");
// 检查客户端是否发送了 If-Modified-Since 或 If-None-Match
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) || isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
$ifModifiedSince = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] : '';
$ifNoneMatch = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? trim($_SERVER['HTTP_IF_NONE_MATCH'], '"') : '';
if (($ifModifiedSince && strtotime($ifModifiedSince) >= $lastModified) ||
($ifNoneMatch && $ifNoneMatch === $etag)) {
header("HTTP/1.1 304 Not Modified");
exit;
}
}
// 如果未命中缓存,输出实际内容
echo file_get_contents(__FILE__);
服务端输出缓存(ob_ 系列函数)
用于捕获 PHP 输出并延迟发送,或实现页面片段缓存。
基本用法:输出缓冲
// 开启输出缓冲 ob_start(); echo "Hello "; echo "World"; // 获取缓冲区内容并清空 $content = ob_get_clean(); echo strtoupper($content); // 输出: HELLO WORLD
回调函数处理输出
function compress_output($buffer) {
// 返回压缩后的内容(示例:移除多余空白)
return preg_replace('/\s+/', ' ', $buffer);
}
ob_start("compress_output");
echo "This is a test string";
ob_end_flush();
实现页面缓存(简单示例)
$cacheFile = '/tmp/cache_' . md5($_SERVER['REQUEST_URI']) . '.html';
$cacheTime = 60; // 缓存60秒
if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < $cacheTime)) {
readfile($cacheFile);
exit;
}
ob_start();
// ... 正常页面输出 ...
echo "<h1>动态内容</h1>";
$content = ob_get_clean();
file_put_contents($cacheFile, $content);
echo $content;
Opcode 缓存(Zend Opcache)
PHP 5.5+ 内置 Opcache,无需额外安装,在 php.ini 中配置即可。
常用配置(php.ini)
[opcache] opcache.enable=1 ; 启用 opcache.memory_consumption=128 ; 共享内存大小(MB) opcache.max_accelerated_files=4000 ; 最大缓存文件数 opcache.revalidate_freq=60 ; 检查文件修改时间间隔(秒) opcache.validate_timestamps=1 ; 启用验证时间戳
通过函数控制(如清除缓存)
// 清除整个 Opcache
opcache_reset();
// 清除指定脚本的缓存
opcache_invalidate('/path/to/file.php', true);
用户态数据缓存(内存/文件)
使用文件缓存
class FileCache {
private $cacheDir;
private $ttl = 3600;
public function __construct($dir = '/tmp/cache') {
$this->cacheDir = $dir;
if (!is_dir($dir)) mkdir($dir, 0755, true);
}
public function get($key) {
$file = $this->cacheDir . '/' . md5($key);
if (file_exists($file) && (time() - filemtime($file) < $this->ttl)) {
return unserialize(file_get_contents($file));
}
return null;
}
public function set($key, $value) {
$file = $this->cacheDir . '/' . md5($key);
file_put_contents($file, serialize($value));
}
public function clear() {
array_map('unlink', glob($this->cacheDir . '/*'));
}
}
// 使用
$cache = new FileCache();
if (!$data = $cache->get('expensive_data')) {
$data = fetchDataFromDatabase(); // 耗时操作
$cache->set('expensive_data', $data);
}
使用 Memcached 或 Redis
// Memcached
$memcached = new Memcached();
$memcached->addServer('localhost', 11211);
$data = $memcached->get('key');
if (!$data) {
$data = getExpensiveData();
$memcached->set('key', $data, 3600);
}
// Redis
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$data = $redis->get('key');
if (!$data) {
$data = getExpensiveData();
$redis->setex('key', 3600, $data);
}
常见问题与最佳实践
| 场景 | 推荐方案 |
|---|---|
| 动态页面(如个人账户) | 设置 Cache-Control: no-cache, must-revalidate + 表单令牌 |
| 静态资源(JS/CSS/图片) | 设置强缓存(max-age=一年)+ 版本号/指纹 |
| API 响应 | 使用 ETag + 304 或设置短时间缓存(如 60 秒) |
| 数据库查询结果 | 使用 Redis/Memcached 缓存查询结果 |
| 整页输出 | 使用 ob_start() + 文件缓存,或 Varnish/CDN |
| PHP 代码本身 | 启用 Opcache(生产环境必须) |
PHP 缓存控制的核心思路:
- 浏览器端:通过 HTTP 头告诉客户端是否缓存、缓存多久
- 服务端输出:用 ob 系列函数捕获和复用生成的内容
- 代码执行:使用 Opcache 编译缓存
- 业务数据:用文件、Memcached 或 Redis 缓存计算结果
根据实际业务场景选择合适的缓存策略,通常需要组合多种方式才能达到最佳性能。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播