laravel 异常深度解析
一、前言
做一件事,不仅要知其然,更要知其所以然。大部分的人都生活在别人设计的世界里,不是没有能力去更深一层,更进一步,而是因为自己懒得去思考。也许自己现在要做的就是:不要让自己舒服吧。
二、正题
1. 定义异常
class StorageException extends MaterialException { /** * @var integer ERROR_CODE 错误代码基数 */ const ERROR_CODE = 12; // 这个有用,后面会讲到 /** * @var string MODULE 模块名称 */ const MODULE = 'storage';// 这个有用,后面会讲到
/** * @var boolean $displayable 是否展示错误信息给前端标记 */ protected $displayable = false; /** * 不上报到sentry的错误码 * * @var array */ protected $dontReport = [12, 15]; /** * 用户自定义异常代码 */ const RECORD_NOT_EXISTS = [10, '资料记录不存在']; const DB_ERROR = [11, '更新数据库出现异常']; const DIR_EXISTS = [12, '目录已存在'];
}
2. 抛出异常
if (empty($announcement)) { list($code, $message) = AnnouncementException::ANNOUNCEMENT_DOES_NOT_EXISTS; throw new AnnouncementException($code, $message); }
3. laravel 捕获异常,怎么捕获的暂时不得而知,等我修炼修炼再来补充。
4. 异常进入到 Handler.php 中去class Handler extends BaseHandler
{ /** * A list of the exception types that should not be reported. * * @var array */ protected $dontReport = [ ]; // 不报告的异常 /** * Report or log an exception. * * This is a great spot to send exceptions to Sentry, Bugsnag, etc. * * @param \Exception $e * @return void */ public function report(Exception $e) { parent::report($e); // 将异常上报,具体的操作看下面 } /** * Render an exception into an HTTP response. * * @param \Illuminate\Http\Request $request * @param \Exception $e * @return \Illuminate\Http\Response */
public function render($request, Exception $e) {
$message = $e->getMessage();
$code = $e->getCode();
$displayable = false; // 异常的具体信息是否可显示给用户
$module = '';
$data = [];
$result = [ 'code' => $code, 'message' => $message, 'displayable' => $displayable, 'module' => $module, 'data' => $data ]; \Log::error("exception response", $result); // 记录错误到日志中 $response = new Response($result, 200); return $response; } }
5. report函数
class BaseHandler extends ExceptionHandler { /** * Report or log an exception. * * This is a great spot to send exceptions to Sentry, Bugsnag, etc. * * @param \Exception $exception * @return void */ public function report(Exception $exception) {
if (app()->environment('production') && $this->shouldReport($exception)) { // app()->environment('production')这个是什么不知道 // shouldReport判断是不是应该报告 if ($exception instanceof SentryException) { // sentry错误就对senrty错误进行处理 $this->dispatchException($exception); } else { app('sentry')->captureException($exception); // 非sentry错误将会捕捉 } } parent::report($exception); // @codeCoverageIgnoreStart } // @codeCoverageIgnoreEnd /** * Method dispatchException * 构造 sentry 日志信息 * * @param Reportable $exception */ private function dispatchException(Reportable $exception) { $httpInstance = HttpInputInfo::getInstance(); $traceId = $httpInstance->getTraceId(); $reportable = $exception->getReportable(); if (!$reportable) { return false; } app('sentry')->captureException($exception, [ 'level' => $exception->getLevelName($exception->getLevel()), 'tags' => [ 'module' => $exception->getModule(), // 上面的module 'code' => $exception->getCode(), // 上面的code 'trace_id' => $traceId, ], 'extra' => $exception->getExtra(), ]); } }
6. render函数
render函数主要是把错误以httpResponse的形式返回