You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

咨询Nginx缓存与Laravel的交互及PHP缓存控制方法

Laravel与Nginx FastCGI缓存的交互实战方案

我来分享下我在Laravel和Nginx FastCGI缓存配合实战中的经验,正好能解决你困惑的几个核心问题——怎么阻止特定请求被缓存、怎么主动清除缓存,还有两者的协作逻辑:

1. 阻止页面/请求被缓存

Nginx的FastCGI缓存会优先响应头的缓存指令,所以我们可以从Laravel层面直接控制,也可以结合Nginx配置做更灵活的判断:

方式一:Laravel直接设置禁止缓存的响应头

在控制器方法或者自定义中间件里,给响应添加标准的缓存控制头,告诉Nginx不要缓存这个请求:

// 单个控制器方法里的写法
return response()->view('dashboard.user')
    ->header('Cache-Control', 'no-cache, no-store, must-revalidate')
    ->header('Pragma', 'no-cache')
    ->header('Expires', '0');

如果是需要给一批路由禁用缓存,写个自定义中间件更高效:

// app/Http/Middleware/DisableCache.php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Response;

class DisableCache
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);
        
        if ($response instanceof Response) {
            $response->headers->set('Cache-Control', 'no-cache, no-store, must-revalidate');
            $response->headers->set('Pragma', 'no-cache');
            $response->headers->set('Expires', '0');
        }
        
        return $response;
    }
}

然后在app/Http/Kernel.php里注册中间件,再给需要的路由绑定就行。

方式二:自定义标记头+Nginx配置判断

这种方式更灵活,比如我们可以在Laravel里给需要跳过缓存的响应加一个自定义头X-Skip-Cache: true,然后在Nginx配置里监听这个头:

# Nginx配置片段
fastcgi_cache_bypass $http_x_skip_cache;
fastcgi_no_cache $http_x_skip_cache;

Laravel里设置这个头的写法很简单:

return response()->view('checkout.cart')->header('X-Skip-Cache', 'true');

2. 主动清除Nginx FastCGI缓存

Nginx本身没有内置的缓存清除API,所以我们需要通过Laravel调用脚本或者精准定位缓存文件来删除,这里有两种常用方案:

方式一:全局清除缓存(Artisan命令)

先确定你的Nginx FastCGI缓存存储路径(比如/var/cache/nginx/fastcgi_cache/),然后写一个Artisan命令来批量删除:

// app/Console/Commands/ClearNginxCache.php
namespace App\Console\Commands;

use Illuminate\Console\Command;
use Symfony\Component\Process\Process;

class ClearNginxCache extends Command
{
    protected $signature = 'nginx:cache:clear {path? : 可选,指定要清除的缓存子路径}';
    protected $description = '清除Nginx FastCGI缓存';

    public function handle()
    {
        $baseCachePath = '/var/cache/nginx/fastcgi_cache/';
        $targetPath = $this->argument('path') ? $baseCachePath . $this->argument('path') : $baseCachePath;
        
        $process = new Process(["rm", "-rf", rtrim($targetPath, '/') . "/*"]);
        $process->run();

        if ($process->isSuccessful()) {
            $this->info('Nginx缓存清除成功!');
        } else {
            $this->error('缓存清除失败:' . $process->getErrorOutput());
        }
    }
}

在app/Console/Kernel.php的$commands数组里注册这个命令,之后就能通过php artisan nginx:cache:clear清除全部缓存,或者指定路径清除某一类缓存。

方式二:精准清除单个页面的缓存

如果只想清除某个特定页面的缓存,需要先还原Nginx的缓存key生成规则,找到对应的缓存文件。比如Nginx里的缓存key配置是:

fastcgi_cache_key "$scheme$request_method$host$request_uri";

那我们在Laravel里生成相同的key,再计算MD5哈希(Nginx用MD5命名缓存文件),然后定位到文件删除:

/**
 * 生成Nginx缓存文件的路径
 * @param string $url 要清除缓存的页面URL
 * @param string $method 请求方法,默认GET
 * @return string
 */
function getNginxCacheFilePath(string $url, string $method = 'GET'): string
{
    $parsed = parse_url($url);
    $scheme = $parsed['scheme'] ?? 'http';
    $host = $parsed['host'];
    $uri = $parsed['path'] . (isset($parsed['query']) ? '?' . $parsed['query'] : '');
    
    $cacheKey = "$scheme$method$host$uri";
    $hash = md5($cacheKey);
    // Nginx会把哈希拆成两级子目录存储
    return "/var/cache/nginx/fastcgi_cache/" . substr($hash, 0, 2) . "/" . substr($hash, 2, 2) . "/" . $hash;
}

// 用法示例:清除某个商品详情页的缓存
$cacheFile = getNginxCacheFilePath('https://your-shop.com/products/123');
if (file_exists($cacheFile)) {
    unlink($cacheFile);
}

3. 分层缓存的协作技巧

Laravel自带的缓存组件(比如Redis、文件缓存)和Nginx FastCGI缓存可以配合使用,实现更高效的分层缓存:

  • 页面的静态框架用Nginx缓存,设置较长的过期时间(比如1小时);
  • 页面里的动态数据(比如用户订单统计、实时库存)用Laravel的@cache指令或者缓存门面存储,设置较短的过期时间;
  • 当动态数据更新时,先清除Laravel对应的缓存,再根据需要清除Nginx的页面缓存(比如商品更新后清除该商品详情页的Nginx缓存)。

内容的提问来源于stack exchange,提问作者Ahmed Nagi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:43:20