CakePHP 3.5 重定向缺少控制器异常

CakePHP 3.5 redirect missing controller exception

我正在为 CakePHP 抛出的缺少控制器异常而苦恼。 调用未知控制器后,它应该在我的登录页面上重定向。 首先,我尝试在 controller/action 未知时路由到我的标准登录页面。

//default routing
$routes->connect('/:controller', ['action' => 'index'], ['routeClass' => 'InflectedRoute']);
$routes->connect('/:controller/:action/*', [], ['routeClass' => 'InflectedRoute']);
$routes->connect('/', ['controller' => 'Users', 'action' => 'login']);
//redirect if controller is not known 
$routes->connect('/*', ['controller' => 'Users', 'action' => 'login']);

然而,这根本不起作用,所以我用谷歌搜索了很多,结果发现你应该捕获一个丢失的控制器异常而不是重新路由。我找不到可以捕获错误的地方,而且关于它的文章很少。

有没有人对此有所了解?

简答

据我所知,捕获 MissinControllerException 只能通过在 Cakephp

中自定义 Error Handling 流程来完成

更长的答案

要达到您想要的结果,需要执行以下操作。

如果您在 Application class 中使用 Middleware,您需要通过注释掉以下行来禁用错误处理中间件:

          ->add(ErrorHandlerMiddleware::class)

接下来,您需要使用自定义错误处理程序覆盖默认的 CakePHP 错误处理程序。因此,在 src\Error 中创建文件 AppError.php,其内容类似于:

class AppError extends ErrorHandler
{

    public function _displayException($exception)
    {
        if($exception instanceof MissingControllerException){
            $response = new Response();
            $response = $response->withLocation(Router::url(
                ['controller'=>'Users', 'action'=>'login'])
            );
            $emitter = new ResponseEmitter();
            $emitter->emit($response);
        }else{
            parent::_displayException($exception);
        }
    }
}

最后,您需要在 bootstrap.php 文件中注册新的错误处理程序。根据文档,需要添加这样的内容:

$errorHandler = new \App\Error\AppError();
$errorHandler->register();

潜在问题

执行此重定向将隐藏所有丢失的控制器异常。如果 URL 中出现拼写错误,这可能会给您带来麻烦,因为您不会再收到明确的错误,而是会被重定向到登录页面。 error.log 文件应该仍然显示原始异常。

祝你好运!

潜在问题 2 - CakePHP >= 3.6.x

正如 ndm 在评论中指出的那样,禁用错误处理中间件并不总是一个好主意,尤其是对于 CakePHP 3.6。在这种情况下,更好的解决方案是扩展 ErrorHandling 中间件并注册它。

您可以尝试使用自定义异常渲染器来处理此异常:

在src/Error中创建一个新文件,命名为MyExceptionRenderer.php,并在那里处理丢失的控制器异常:

namespace App\Error;

use Cake\Error\ExceptionRenderer;

class MyExceptionRenderer extends ExceptionRenderer
{
    public function missingController($error)
    {
        return $this->controller->redirect("/");
    }
}

您还需要在 config/app 中启用此自定义渲染器。php:

'Error' => [
    'errorLevel' => E_ALL,
    'exceptionRenderer' => 'App\Error\MyExceptionRenderer',
    'skipLog' => [],
    'log' => true,
    'trace' => true,
],

有了这个,当 MissingControllerException 被引发时,用户将被重定向,在这种情况下到主页。

可以在此处找到更多信息:Error Handling