Slim4です。
エラー周りの基本処理で。
* @param bool $displayErrorDetails -> Should be set to false in production
* @param bool $logErrors -> Parameter is passed to the default ErrorHandler
* @param bool $logErrorDetails -> Display error details in error log
* which can be replaced by a callable of your choice.
* @param \Psr\Log\LoggerInterface $logger -> Optional PSR-3 logger to receive errors
ってなコメントもございますので、おいちゃんは大概
$errorMiddleware = $app->addErrorMiddleware($container->get('settings')['displayErrorDetails'], true, true, $container->get('logger'));
って書いておくでございます。
ただ、これだけだと「404もエラーログに書かれるので結構ウザい」でございます。
いや「Slimのエラーを一通りログに出さない」んなら
$errorMiddleware = $app->addErrorMiddleware($container->get('settings')['displayErrorDetails'], true, true);
でよいのですが、「404以外のエラーは念のために補足しておきたい」んですよねぇ、という乙女心*1。
まぁ色々調べてみるわけなのですが。
まず「エラー時に任意の画面を出したい」場合、
https://www.slimframework.com/docs/v4/middleware/error-handling.html
に
// Get the default error handler and register my custom error renderer.
$errorHandler = $errorMiddleware->getDefaultErrorHandler();
$errorHandler->registerErrorRenderer('text/html', MyCustomErrorRenderer::class);
ってな記述があるのでございます。
なお上述クラスは
<?php
use Slim\Interfaces\ErrorRendererInterface;
class MyCustomErrorRenderer implements ErrorRendererInterface
{
public function __invoke(Throwable $exception, bool $displayErrorDetails): string
{
return 'My awesome format';
}
}
こんな風に実装する感じでございます。
さて。
とりあえずgetDefaultErrorHandler()てのがあるので、軽くgrepります*2。
"vendor/slim/slim/Slim/Middleware/ErrorMiddleware.php"
public function getDefaultErrorHandler()
{
if ($this->defaultErrorHandler === null) {
$this->defaultErrorHandler = new ErrorHandler(
$this->callableResolver,
$this->responseFactory,
$this->logger
);
}
return $this->callableResolver->resolve($this->defaultErrorHandler);
}
getがあるんならsetもあるんじゃなかろうか。
public function setDefaultErrorHandler($handler): self
{
$this->defaultErrorHandler = $handler;
return $this;
}
DefaultがあるんならDefault無しもあるんじゃなかろうか。
public function setErrorHandler($typeOrTypes, $handler, bool $handleSubclasses = false): self
{
if (is_array($typeOrTypes)) {
foreach ($typeOrTypes as $type) {
$this->addErrorHandler($type, $handler, $handleSubclasses);
}
} else {
$this->addErrorHandler($typeOrTypes, $handler, $handleSubclasses);
}
return $this;
}
ここからちゃんとコードを確認してもよいのですが……面倒なんでvar_dumpで調査します。
つまり
・setErrorHandler()の先頭に var_dump($typeOrTypes); exit; を仕込んで
・404をわざと発生させます
まぁ予想通り Slim\Exception\HttpNotFoundException でございます(Slim4、この辺は例外のクラスで判別するので)。
ってことは
public function getErrorHandler(string $type)
{
if (isset($this->handlers[$type])) {
return $this->callableResolver->resolve($this->handlers[$type]);
} elseif (isset($this->subClassHandlers[$type])) {
return $this->callableResolver->resolve($this->subClassHandlers[$type]);
} else {
foreach ($this->subClassHandlers as $class => $handler) {
if (is_subclass_of($type, $class)) {
return $this->callableResolver->resolve($handler);
}
}
}
return $this->getDefaultErrorHandler();
}
これも大体予想通り。
なので、ざっくりと実装してみます。
$errorMiddleware->setErrorHandler(\Slim\Exception\HttpNotFoundException::class, function($request, $e) use($app){
$response = $app->getResponseFactory()->createResponse(404);
$response->getBody()->write('めっからないよん??');
return $response;
});
確認……うん、OK。
というわけで、備忘録を兼ねて、メモ。