CakePHP 4.0自定义错误模板不生效 无法渲染missingController等异常页
CakePHP 4.x 自定义错误模板渲染相关问题
问题背景
在CakePHP 3.x版本中,通过继承自AppController的ErrorController、存放于src/Error/目录下的自定义AppExceptionRenderer,可正常实现异常自定义渲染。迁移至4.0版本后,所有错误与异常仅渲染error400或error500页面:
- 错误请求可进入
ErrorController::initialize()方法,但无法触发ErrorController的beforeFilter回调(该回调在3.x版本中可正常执行) - 项目已在
Application.php中引入Authentication、Authorization、RequestAuthorization三类中间件 templates/Error目录下除error400、error500模板外,已存放missingController、missingTemplate、missingAction三类异常对应的3个自定义模板- 访问不存在的控制器/动作时,4.0版本直接渲染error500页面,3.x版本可正常匹配渲染对应的missingController/missingAction页面
相关代码
src/Application.php 中间件配置
$middlewareQueue .... ->add(new AuthenticationMiddleware($this)) ->add(new AuthorizationMiddleware($this, [ 'requireAuthorizationCheck' => true, 'unauthorizedHandler' => [ 'className' => 'CustomRedirect', 'url' => '/pages/permission', 'exceptions' => [ 'MissingIdentityException' => 'Authorization\Exception\MissingIdentityException', 'ForbiddenException' => 'Authorization\Exception\ForbiddenException' ], ], ])) ->add(new RequestAuthorizationMiddleware());
RequestPolicy 接口 canAccess 方法实现
public function canAccess($identity, ServerRequest $request) { $unauthenticatedActions = $request->getAttribute('authentication')->getConfig('unauthenticatedActions'); if (in_array($request->getParam('action'), $unauthenticatedActions, true)) { return true; } else if(!empty($identity)){ // 基于动作和用户角色做权限校验 $userRole = $identity->role; $userStatus = $identity->status; $accountType = $identity->accountsubType; $action = $request->getParam('action'); $controller = $request->getParam('controller'); switch ($controller) { case 'Users': if($userRole === 'ADMIN' && $userStatus === 'ACTIVE'){ return true; }elseif($action === 'aaa'){ // 对应权限判断逻辑 } break; // 其余控制器权限判断逻辑 .... default: // 无匹配控制器名称时默认放行 return true; } }
src/Error/AppExceptionRenderer.php
namespace App\Error; use Cake\Error\ExceptionRenderer; use Psr\Http\Message\ResponseInterface; use Cake\Core\Configure; use Cake\Http\Session; class AppExceptionRenderer extends ExceptionRenderer { public function render(): ResponseInterface { // 自定义变量设置逻辑 ... ... return parent::render(); } }
templates/Error 目录结构

错误堆栈
访问不存在的路由/users/random时触发异常,堆栈信息如下:
Error: [Cake\Controller\Exception\MissingActionException] Action UsersController::random() could not be found, or is not accessible. in ../vendor/cakephp/cakephp/src/Controller/Controller.php on line 500 Exception Attributes: array ( 'controller' => 'UsersController', 'action' => 'random', 'prefix' => '', 'plugin' => NULL, ) Stack Trace: - .../vendor/cakephp/cakephp/src/Controller/ControllerFactory.php:77 - .../vendor/cakephp/cakephp/src/Http/BaseApplication.php:229 - .../vendor/cakephp/cakephp/src/Http/Runner.php:77 - .../vendor/cakephp/authorization/src/Middleware/RequestAuthorizationMiddleware.php:102 - .../vendor/cakephp/cakephp/src/Http/Runner.php:73 - .../vendor/cakephp/authorization/src/Middleware/AuthorizationMiddleware.php:129 - .../vendor/cakephp/cakephp/src/Http/Runner.php:73 - .../vendor/cakephp/authentication/src/Middleware/AuthenticationMiddleware.php:124 - .../vendor/cakephp/cakephp/src/Http/Runner.php:73 - .../vendor/cakephp/cakephp/src/Http/Middleware/BodyParserMiddleware.php:159 - .../vendor/cakephp/cakephp/src/Http/Runner.php:73 - .../vendor/cakephp/cakephp/src/Routing/Middleware/RoutingMiddleware.php:160 - .../vendor/cakephp/cakephp/src/Http/Runner.php:73 - .../vendor/cakephp/cakephp/src/Routing/Middleware/AssetMiddleware.php:68 - .../vendor/cakephp/cakephp/src/Http/Runner.php:73 - .../vendor/cakephp/cakephp/src/Error/Middleware/ErrorHandlerMiddleware.php:119 - .../vendor/cakephp/cakephp/src/Http/Runner.php:73 - .../vendor/cakephp/cakephp/src/Http/Middleware/EncryptedCookieMiddleware.php:93 - .../vendor/cakephp/cakephp/src/Http/Runner.php:73 - .../vendor/cakephp/debug_kit/src/Middleware/DebugKitMiddleware.php:60 - .../vendor/cakephp/cakephp/src/Http/Runner.php:73 - .../vendor/cakephp/cakephp/src/Http/Runner.php:58 - .../vendor/cakephp/cakephp/src/Http/Server.php:90 - .../webroot/index.php:91 Request URL: /users/random
待解决问题
- CakePHP 4.x版本中如何正确配置,才能让missingController等自定义错误模板正常渲染,而非默认返回error500页面
- 如何让错误请求经过ErrorController的beforeFilter回调,以实现自定义日志记录逻辑
内容的提问来源于stack exchange,提问作者EssEss
相关产品推荐
相关产品推荐

