feat: 前台整页响应缓存(匿名 GET,浏览量走 track-view 独立端点)+ 后台缓存管理页 + 侧边栏 nav-groups 负 margin 归零
This commit is contained in:
@@ -25,7 +25,7 @@ class PostController extends Controller
|
||||
|
||||
$this->ensureReadable($post);
|
||||
|
||||
$post->increment('views');
|
||||
// 浏览量由 /track-view 端点统计(页面整页缓存下控制器不执行,避免双计)
|
||||
|
||||
$comments = $post->comments()
|
||||
->where('status', 'published')
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Blog\Support;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* 前台页面响应缓存:
|
||||
* - 仅缓存匿名 GET 请求的 HTML 页面(首页/列表/文章/归档/标签等)
|
||||
* - 登录用户、后台、API、动态端点不缓存
|
||||
* - 浏览量走独立的 /track-view 端点,不受整页缓存影响
|
||||
*/
|
||||
class PageCacheMiddleware
|
||||
{
|
||||
public const TAG = 'pages';
|
||||
|
||||
public function handle(Request $request, \Closure $next): Response
|
||||
{
|
||||
if (! $this->shouldCache($request)) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
$key = $this->key($request);
|
||||
$ttl = (int) config('blog.page_cache_ttl', 300);
|
||||
|
||||
if ($cached = Cache::get($key)) {
|
||||
return response($cached['body'], 200, [
|
||||
'Content-Type' => $cached['type'],
|
||||
'Cache-Control' => 'public, max-age='.$ttl,
|
||||
]);
|
||||
}
|
||||
|
||||
$response = $next($request);
|
||||
|
||||
if ($response->getStatusCode() === 200) {
|
||||
Cache::put($key, [
|
||||
'body' => $response->getContent(),
|
||||
'type' => $response->headers->get('Content-Type') ?: 'text/html; charset=utf-8',
|
||||
], $ttl);
|
||||
self::rememberKey($key);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public static function flush(): void
|
||||
{
|
||||
foreach ((array) Cache::get(self::TAG.'_keys', []) as $key) {
|
||||
Cache::forget($key);
|
||||
}
|
||||
|
||||
Cache::forget(self::TAG.'_keys');
|
||||
}
|
||||
|
||||
public static function count(): int
|
||||
{
|
||||
return count((array) Cache::get(self::TAG.'_keys', []));
|
||||
}
|
||||
|
||||
private static function rememberKey(string $key): void
|
||||
{
|
||||
$keys = (array) Cache::get(self::TAG.'_keys', []);
|
||||
$keys[$key] = true;
|
||||
Cache::put(self::TAG.'_keys', $keys, now()->addDay());
|
||||
}
|
||||
|
||||
private function shouldCache(Request $request): bool
|
||||
{
|
||||
if (! $request->isMethod('GET')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (auth()->check()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$path = $request->path();
|
||||
|
||||
if (str_starts_with($path, 'admin') || str_starts_with($path, 'api') || str_starts_with($path, 'themes')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 动态端点
|
||||
if (str_starts_with($path, 'track-view')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function key(Request $request): string
|
||||
{
|
||||
return self::TAG.':'.md5($request->fullUrl());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user