如果发生 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;
}

另见