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
我正在为 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
更长的答案
要达到您想要的结果,需要执行以下操作。
如果您在 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