Featured image of post Slim4 中使用中间件缓存请求

Slim4 中使用中间件缓存请求

在 Slim 框架中进行 API 接口缓存

  • 我们不管写页面还是写接口的时候,经常会用到一个功能。
  1. 通常一个请求过来,我们从数据库中查询出来,然后数据转换处理完成之后返回
  2. 但是有一些页面,比如首页或者某个接口数据不是经常改动的,请求多了,会造成影响
  3. 所以,我们可以第一次请求处理完成输出之前,把内容缓存到Redis之类的存储
  4. 下次再请求这个,先从Redis读取数据,没过期直接返回不需要处理。
  5. 如果缓存过期,那么重复 [3, 4]
  • 以下是Slim4框架中的实现
<?php

namespace App\Middleware;


use Nyholm\Psr7\Stream;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;

class PageCacheMiddleware
{

    public function __invoke(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        $paths = [
            '/' => [],
            '/categories' => [],
            '/articles' => [],
        ];
        $requestPath = $request->getUri()->getPath();

        // 不需要缓存的路由
        if (
            (strtoupper($request->getMethod()) !== 'GET') ||
            ! array_key_exists($path, $configs)
        ) {

            return $handler->handle($request);
        }


        // 可能,你的 cacheKey 还需要加一些参数辨别,例如 page=1
        $requestParameters = $request->getQueryParams();
        $cacheKey = base64_encode($requestPath . json_encode($requestParameters));

        // 这里,你可以从缓存中获取,这里为了演示简单,直接通过文件读写来达到缓存的效果
        if (file_exists($cacheKey)) {

            list($cacheResponse, $cacheContent) = unserialize(file_get_contents($cacheKey));
            if ($cacheResponse instanceof ResponseInterface) {

                $newResponse = $cacheResponse->withBody(Stream::create($cacheContent));
                return $newResponse;
            }
        }

        $response = $handler->handle($request);

        // 这里,我们把这个 Response 对象缓存起来,因为我们需要响应头等信息,
        // 还缓存了 body,这里最为重要,slim4 的 body 使用 php_temp 流,
        // 而 PHP 中说到,流是不能序列化的。所以我们也缓存一个内容
        file_put_contents($cacheKey, serialize([$response, (string)$response->getBody()]));

        return $response;
    }
}