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

Slim框架响应缓存咨询:共享主机适配方案及自定义Middleware指引

Hey there! Let me break down practical, shared-host-friendly ways to add response caching with Memcached or Redis to your Slim app—including how to build your own middleware if existing solutions aren't cutting it.

First: Confirm Shared Host Support

Before diving in, you need to make sure your host allows access to Memcached/Redis:

  • Create a quick phpinfo.php file with <?php phpinfo(); ?>, upload it, and check for memcached or redis extensions. If they're missing, reach out to your host to enable them. If they can't, use a pure-PHP client like Predis for Redis (it works without extensions, though performance is slightly lower).
  • Verify your host gives you the correct connection details (host, port, password if required)—shared hosts often use specific local addresses instead of localhost.
Try Existing (Slim-Friendly) Libraries First

You mentioned trying some methods without luck—here's a more targeted approach:

  • Use PSR-16 compliant cache libraries (Slim plays nice with these). For example, league/cache works with both Memcached and Redis, and you can wrap it in a Slim middleware to cache responses.
  • If you go the Redis route, install predis/predis via Composer (if you can't use SSH on your host, install locally then upload the vendor folder).
Build Your Own Response Cache Middleware (Step-by-Step)

If rolling your own feels more reliable for your shared host setup, here's a clear roadmap:

Step 1: Add Cache Settings to Your Slim Config

Define your cache driver and connection details in your app's config:

$config = [
    'settings' => [
        'cache' => [
            'driver' => 'memcached', // Swap to 'redis' if needed
            'host' => 'your-host-cache-address',
            'port' => 11211, // Memcached default; Redis uses 6379
            'prefix' => 'slim_myapp_', // Avoid key collisions with other host users
            'ttl' => 3600, // Cache responses for 1 hour by default
            'password' => 'your-cache-password' // Only if required
        ],
    ],
];

Step 2: Register the Cache Client in Slim's Container

Set up the cache client so your middleware can access it:

$app->getContainer()->set('cache', function ($c) {
    $settings = $c->get('settings')['cache'];
    
    if ($settings['driver'] === 'memcached') {
        $client = new Memcached();
        $client->addServer($settings['host'], $settings['port']);
        // Add auth if your host requires it
        if (!empty($settings['password'])) {
            $client->setOption(Memcached::OPT_BINARY_PROTOCOL, true);
            $client->setSaslAuthData($settings['username'] ?? '', $settings['password']);
        }
        return $client;
    } elseif ($settings['driver'] === 'redis') {
        return new Predis\Client([
            'scheme' => 'tcp',
            'host' => $settings['host'],
            'port' => $settings['port'],
            'password' => $settings['password'] ?? null,
        ]);
    }
    
    throw new RuntimeException('Unsupported cache driver selected');
});

Step 3: Write the Cache Middleware

This middleware will check for cached responses first, then cache new ones after processing:

class ResponseCacheMiddleware
{
    private $cache;
    private $cacheSettings;

    public function __construct($cache, array $cacheSettings)
    {
        $this->cache = $cache;
        $this->cacheSettings = $cacheSettings;
    }

    public function __invoke($request, $response, $next)
    {
        // Generate a unique cache key based on request method, path, and query params
        $requestSignature = md5(
            $request->getMethod() . 
            $request->getUri()->getPath() . 
            http_build_query($request->getQueryParams())
        );
        $cacheKey = $this->cacheSettings['prefix'] . $requestSignature;

        // Check for cached response
        $cachedResponse = false;
        if ($this->cache instanceof Memcached) {
            $cachedResponse = $this->cache->get($cacheKey);
        } elseif ($this->cache instanceof Predis\Client) {
            $cachedResponse = $this->cache->get($cacheKey);
        }

        if ($cachedResponse !== false) {
            // Unserialize and return the cached response
            $cachedData = unserialize($cachedResponse);
            return $response->withStatus($cachedData['status'])
                ->withHeaders($cachedData['headers'])
                ->write($cachedData['body']);
        }

        // No cache hit—process the request normally
        $processedResponse = $next($request, $response);

        // Prepare response data for caching
        $responseData = [
            'status' => $processedResponse->getStatusCode(),
            'headers' => $processedResponse->getHeaders(),
            'body' => (string)$processedResponse->getBody(),
        ];

        // Store the response in cache
        $ttl = $this->cacheSettings['ttl'];
        if ($this->cache instanceof Memcached) {
            $this->cache->set($cacheKey, serialize($responseData), $ttl);
        } elseif ($this->cache instanceof Predis\Client) {
            $this->cache->setex($cacheKey, $ttl, serialize($responseData));
        }

        return $processedResponse;
    }
}

Step 4: Attach the Middleware to Your App

You can add it globally (for all routes) or to specific routes:

// Global middleware (applies to every route)
$app->add(new ResponseCacheMiddleware(
    $app->getContainer()->get('cache'),
    $app->getContainer()->get('settings')['cache']
));

// Or attach to a single route
$app->get('/api/statistics', function ($request, $response) {
    // Your route logic here
})->add(new ResponseCacheMiddleware(
    $app->getContainer()->get('cache'),
    $app->getContainer()->get('settings')['cache']
));
Critical Shared Host Tips
  • Key Prefixes: Always use a unique prefix for cache keys—shared hosts often have multiple apps using the same Memcached/Redis instance, so this avoids overwriting other users' data.
  • Composer Workaround: If your host doesn't allow SSH, install dependencies locally with composer install --no-dev, then upload the entire vendor folder to your host.
  • Cache Invalidation: Add logic to delete relevant cache keys when you update data (e.g., after saving a post, delete the cache key for the post list route).
  • Debugging: Add a custom header like X-Cache: HIT or X-Cache: MISS in your middleware to easily verify if caching is working.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:16:31