When developing web pages or API interfaces, we often encounter the following scenario:
- A request is processed by querying the database and returning transformed data
- Some pages/interfaces with infrequent data changes (e.g. homepage) may experience performance issues under high traffic
- Solution: Cache processed content in storage like Redis before returning the response
- Subsequent requests first check the cache - return immediately if valid
- If cache expires, repeat steps [3-4]
Here’s an implementation in Slim4 framework:
<?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
{
$cachedRoutes = [
'/' => [],
'/categories' => [],
'/articles' => [],
];
$requestPath = $request->getUri()->getPath();
// Bypass non-GET requests and uncached routes
if (
(strtoupper($request->getMethod()) !== 'GET') ||
!array_key_exists($requestPath, $cachedRoutes)
) {
return $handler->handle($request);
}
// Generate cache key considering query parameters
$requestParameters = $request->getQueryParams();
$cacheKey = base64_encode($requestPath . json_encode($requestParameters));
// Simulating cache storage with file system (replace with Redis in production)
if (file_exists($cacheKey)) {
list($cachedResponse, $cachedBody) = unserialize(file_get_contents($cacheKey));
if ($cachedResponse instanceof ResponseInterface) {
return $cachedResponse->withBody(Stream::create($cachedBody));
}
}
// Process request and cache response
$response = $handler->handle($request);
file_put_contents(
$cacheKey,
serialize([$response, (string)$response->getBody()])
);
return $response;
}
}
Key implementation details:
- Only cache specified GET routes
- Cache key includes URL path and query parameters
- Serializes both response object and body content
- File-based caching for demonstration (replace with Redis/Memcached in production)
This middleware checks the cache before processing requests and stores responses after initial processing, effectively reducing database queries and computational overhead for cached endpoints.