Slim4で「404のログ」だけ消したい(&任意のエラー画面出したい)
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。
というわけで、備忘録を兼ねて、メモ。