如何在Phalcon中处理500和200错误并创建默认错误页面?
在Phalcon中处理500、200错误与自定义错误页面的最佳实践
结合你提供的service.php代码,我们可以通过以下步骤实现统一的错误处理和自定义错误页面:
一、扩展Dispatcher异常处理,覆盖500错误
在现有Dispatcher的dispatch:beforeException事件回调中,添加对500内部服务器错误的处理逻辑:
use \Phalcon\Mvc\Dispatcher as PhDispatcher; $di->set( 'dispatcher', function() use ($di) { $evManager = $di->getShared('eventsManager'); $evManager->attach( "dispatch:beforeException", function($event, $dispatcher, $exception) use ($di) { switch ($exception->getCode()) { case PhDispatcher::EXCEPTION_HANDLER_NOT_FOUND: case PhDispatcher::EXCEPTION_ACTION_NOT_FOUND: $dispatcher->forward([ 'namespace' => 'App\Controllers\Web', 'controller' => 'error', 'action' => 'show404', ]); return false; default: // 处理所有未捕获的异常,作为500错误 $dispatcher->forward([ 'namespace' => 'App\Controllers\Web', 'controller' => 'error', 'action' => 'show500', ]); // 记录异常日志(需提前配置logger服务) $logger = $di->getShared('logger'); $logger->error( $exception->getMessage() . PHP_EOL . $exception->getTraceAsString() ); return false; } } ); $dispatcher = new PhDispatcher(); $dispatcher->setEventsManager($evManager); return $dispatcher; }, true );
二、创建Error控制器,处理错误页面渲染
在app/controllers/Web/目录下创建ErrorController.php,包含404、500以及200响应的处理方法:
<?php namespace App\Controllers\Web; use Phalcon\Mvc\Controller; class ErrorController extends Controller { // 404页面处理 public function show404Action() { $this->response->setStatusCode(404, 'Not Found'); $this->view->pick('error/404'); } // 500页面处理 public function show500Action() { $this->response->setStatusCode(500, 'Internal Server Error'); // 开发环境可传递异常详情,生产环境建议隐藏 if ($this->config->app->debug) { $exception = $this->dispatcher->getParam('exception'); $this->view->setVar('exception', $exception); } $this->view->pick('error/500'); } // 统一200成功响应处理(可选,用于页面或接口统一格式) public function show200Action() { $this->response->setStatusCode(200, 'OK'); // 根据需求渲染视图或返回JSON // $this->view->pick('success/200'); } }
三、创建自定义错误视图
在app/views/目录下创建error文件夹,分别添加404和500的视图文件:
404视图(app/views/error/404.volt)
<!DOCTYPE html> <html> <head> <title>404 - 页面未找到</title> <style> .error-wrap { text-align: center; padding: 60px 0; } h1 { font-size: 3.5em; color: #dc3545; margin: 0; } p { font-size: 1.2em; margin: 15px 0; } a { color: #0d6efd; text-decoration: none; } </style> </head> <body> <div class="error-wrap"> <h1>404</h1> <p>抱歉,您访问的页面不存在或已被移除</p> <a href="/">返回首页</a> </div> </body> </html>
500视图(app/views/error/500.volt)
<!DOCTYPE html> <html> <head> <title>500 - 服务器内部错误</title> <style> .error-wrap { text-align: center; padding: 60px 0; } h1 { font-size: 3.5em; color: #dc3545; margin: 0; } p { font-size: 1.2em; margin: 15px 0; } a { color: #0d6efd; text-decoration: none; } .debug-info { text-align: left; max-width: 800px; margin: 30px auto; padding: 20px; background: #f8f9fa; border-radius: 5px; } </style> </head> <body> <div class="error-wrap"> <h1>500</h1> <p>服务器内部出现错误,请稍后重试</p> <a href="/">返回首页</a> {% if exception %} <div class="debug-info"> <h3>错误详情:</h3> <p><strong>消息:</strong>{{ exception.getMessage() }}</p> <p><strong>位置:</strong>{{ exception.getFile() }} 第 {{ exception.getLine() }} 行</p> <p><strong>调用栈:</strong></p> <pre>{{ exception.getTraceAsString() }}</pre> </div> {% endif %} </div> </body> </html>
四、全局PHP错误处理(可选)
为了捕获PHP致命错误、警告等非Dispatcher级别的错误,可在services.php中注册ErrorHandler:
use Phalcon\ErrorHandler; $di->set('errorHandler', function() use ($di) { $errorHandler = new ErrorHandler(); $errorHandler->setErrorTypes(E_ALL); $evManager = $di->getShared('eventsManager'); $errorHandler->attach($evManager); // 注册全局错误处理 $errorHandler->register(); return $errorHandler; }, true); // 监听error事件,处理致命错误 $evManager->attach('error', function($event, $errorHandler, $exception) use ($di) { $logger = $di->getShared('logger'); $logger->error($exception->getMessage() . PHP_EOL . $exception->getTraceAsString()); if ($event->getType() === 'fatal') { ob_clean(); $response = $di->getShared('response'); $response->setStatusCode(500, 'Internal Server Error'); $view = $di->getShared('view'); $view->pick('error/500'); echo $view->render(); exit(); } });
五、200成功响应的统一处理(可选)
如果需要统一所有成功请求的响应格式(比如页面布局、API JSON结构),可以创建基础控制器:
<?php namespace App\Controllers\Web; use Phalcon\Mvc\Controller; class BaseController extends Controller { public function afterExecuteRoute($dispatcher) { // 统一设置200状态码 $this->response->setStatusCode(200, 'OK'); // 统一设置页面布局 $this->view->setLayout('default'); } }
所有业务控制器继承BaseController即可自动应用统一规则。
内容的提问来源于stack exchange,提问作者Van Pham
相关产品推荐
相关产品推荐

