如果发生 MissingControllerException,CakePHP 3.x 从日志记录中捕获选定的控制器
CakePHP 3.x catch selected controller from logging if MissingControllerException occurs
在 CakePHP 3.x 中,如果发生 MissingControllerException,我如何从登录 error.log 文件中捕获选定的控制器名称。
目前我有日志例如:
2022-02-17 09:32:34 Error: [Cake\Routing\Exception\MissingControllerException] Controller class AAA could not be found.
我尝试在 src/Error 文件夹中写入自己的 MyExceptionRenderer.php:
namespace App\Error;
use Cake\Error\ExceptionRenderer;
class MyExceptionRenderer extends ExceptionRenderer{
public function missingController($error){
// Logic if AAA occuress do sth, e.g. redirect to selected page
}
}
在app.php中我添加了:
'Error' => [
'errorLevel' => E_ALL & ~E_DEPRECATED,
'exceptionRenderer' => 'App\Error\MyExceptionRenderer',
'skipLog' => [],
'log' => true,
'trace' => true,
],
但是不行
如评论中所述,我没有发现显示的代码有任何问题,我已经尝试过 1:1,它对我使用 CakePHP 3.10.2、missingController()
正在按预期调用方法。
如果正在使用您的渲染器,但未调用该方法,则您必须调试正在扩展的核心异常渲染器,并找出 \Cake\Error\ExceptionRenderer::_customMethod()
时到底发生了什么应该被调用。
也就是说,我可能会为此使用自定义中间件,因为您实际上并不打算进行异常呈现。将它放在错误处理程序中间件之后并捕获您想要捕获的异常,大致如下:
// in src/Middleware/MissingControllerHandlerMiddleware.php
namespace App\Middleware;
use Cake\Routing\Exception\MissingControllerException;
use Cake\Utility\Hash;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class MissingControllerHandlerMiddleware
{
/**
* Invoke method.
*
* @param \Psr\Http\Message\ServerRequestInterface $request The request.
* @param \Psr\Http\Message\ResponseInterface $response The response.
* @param callable $next Callback to invoke the next middleware.
* @return \Psr\Http\Message\ResponseInterface A response
*/
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next)
{
try {
return $next($request, $response);
} catch (MissingControllerException $exception) {
$class = Hash::get($exception->getAttributes(), 'class');
if ($class === 'AAA') {
return $response->withHeader('Location', 'https://example.com/missing-aaa-controller-redirect');
}
if ($class === 'BBB') {
// ...
}
// ...
throw $exception;
}
}
}
// in src/Application.php
public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
{
$middlewareQueue
->add(new ErrorHandlerMiddleware(Configure::read('Error')))
->add(new \App\Middleware\MissingControllerHandlerMiddleware())
// ...
return $middlewareQueue;
}
另见
在 CakePHP 3.x 中,如果发生 MissingControllerException,我如何从登录 error.log 文件中捕获选定的控制器名称。
目前我有日志例如:
2022-02-17 09:32:34 Error: [Cake\Routing\Exception\MissingControllerException] Controller class AAA could not be found.
我尝试在 src/Error 文件夹中写入自己的 MyExceptionRenderer.php:
namespace App\Error;
use Cake\Error\ExceptionRenderer;
class MyExceptionRenderer extends ExceptionRenderer{
public function missingController($error){
// Logic if AAA occuress do sth, e.g. redirect to selected page
}
}
在app.php中我添加了:
'Error' => [
'errorLevel' => E_ALL & ~E_DEPRECATED,
'exceptionRenderer' => 'App\Error\MyExceptionRenderer',
'skipLog' => [],
'log' => true,
'trace' => true,
],
但是不行
如评论中所述,我没有发现显示的代码有任何问题,我已经尝试过 1:1,它对我使用 CakePHP 3.10.2、missingController()
正在按预期调用方法。
如果正在使用您的渲染器,但未调用该方法,则您必须调试正在扩展的核心异常渲染器,并找出 \Cake\Error\ExceptionRenderer::_customMethod()
时到底发生了什么应该被调用。
也就是说,我可能会为此使用自定义中间件,因为您实际上并不打算进行异常呈现。将它放在错误处理程序中间件之后并捕获您想要捕获的异常,大致如下:
// in src/Middleware/MissingControllerHandlerMiddleware.php
namespace App\Middleware;
use Cake\Routing\Exception\MissingControllerException;
use Cake\Utility\Hash;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class MissingControllerHandlerMiddleware
{
/**
* Invoke method.
*
* @param \Psr\Http\Message\ServerRequestInterface $request The request.
* @param \Psr\Http\Message\ResponseInterface $response The response.
* @param callable $next Callback to invoke the next middleware.
* @return \Psr\Http\Message\ResponseInterface A response
*/
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next)
{
try {
return $next($request, $response);
} catch (MissingControllerException $exception) {
$class = Hash::get($exception->getAttributes(), 'class');
if ($class === 'AAA') {
return $response->withHeader('Location', 'https://example.com/missing-aaa-controller-redirect');
}
if ($class === 'BBB') {
// ...
}
// ...
throw $exception;
}
}
}
// in src/Application.php
public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
{
$middlewareQueue
->add(new ErrorHandlerMiddleware(Configure::read('Error')))
->add(new \App\Middleware\MissingControllerHandlerMiddleware())
// ...
return $middlewareQueue;
}
另见