However, in the app.log file, you can see the value retrieved from the memcached object is empty:
[2020-10-05 01:51:12] slim-app.INFO: Last throttle time: [] {“uid”:“077eeee”}
You will notice too, that I’m using service locator in the constructor of my action which I would also perfer not to do. Any guidance would be appreciated. I’m at a loss.
I would always try to seperate the container configuration from the request / response context. In other words: Configure the dependencies in your container and use the request / response objects only within the Action class or the middleware.
First create a “MemcachedThrottleKeyMiddleware” class that puts the throttle key. Then fetch the key from memecache in your action (or better within a repository).
Example:
// Build PHP-DI Container instance
$container = $containerBuilder->build();
// Use the classname as container key
$container->set(Memcached::class, function () {
$mc = new Memcached();
$mc->addServer('127.0.0.1', 11211);
return $mc;
});
AppFactory::setContainer($container);
// Instantiate the app
// ...
// Add the middleware
// ...
$app->add(\App\Middleware\MemcachedThrottleKeyMiddleware::class); // <-- here
$app->add(ErrorMiddleware::class);
// Add routes
// ...
$app->run();
The middleware:
<?php
namespace App\Middleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Memcached;
final class MemcachedThrottleKeyMiddleware implements MiddlewareInterface
{
/**
* @var Memcached
*/
private $memcached;
public function __construct(Memcached $memcached)
{
$this->memcached = $memcached;
}
public function process(
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface
{
$memcachedThrottleKey = 'my-domain/throttle-key-' . $request->getServerParams()['REMOTE_ADDR'];
$this->memcached->set($memcachedThrottleKey, date("Y-m-d h:i:s"));
$request = $request->withAttribute('memcachedThrottleKey', $memcachedThrottleKey);
return $handler->handle($request);
}
}
}
Hi odan, thank you for your reply. I’ve spent some time implementing your solution, which creates a better separation of concerns. However, unfortunately I’m still not seeing the cached value in the logs. Full disclosure; triple-checks lead me to believe I have configured this properly. I’m not ruling out shared hosting issues with Memcached.
[2020-10-05 20:45:42] slim-app.INFO: Last throttle time: [] {"uid":"c7e34b1"}
The Middleware:
<?php
namespace App\Application\Middleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Memcached;
final class MemcachedThrottleKeyMiddleware implements MiddlewareInterface
{
/**
* @var Memcached
*/
private $memcached;
public function __construct(Memcached $memcached)
{
$this->memcached = $memcached;
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$memcachedThrottleKey = 'my-domain/throttle-key-' . $request->getServerParams()['REMOTE_ADDR'];
$this->memcached->set($memcachedThrottleKey, date("Y-m-d h:i:s"));
$request = $request->withAttribute('memcachedThrottleKey', $memcachedThrottleKey);
return $handler->handle($request);
}
}
index.php:
$container->set(Memcached::class, function () {
$mc = new Memcached();
$mc->addServer('127.0.0.1', 11211);
return $mc;
});
middleware.php:
<?php
declare(strict_types=1);
use App\Application\Middleware\SessionMiddleware;
use App\Application\Middleware\MemcachedThrottleKeyMiddleware;
use Slim\App;
return function (App $app) {
$app->add(SessionMiddleware::class);
$app->add(MemcachedThrottleKeyMiddleware::class);
$app->addBodyParsingMiddleware();
};
ContactAction extends MailerAction which extends Action. Again; I believe this is setup and configured properly and the solution provided by you (odan) is the best. Memcached is simply prohibited by GoDaddy’s economy tier.