├── config └── config.php ├── src ├── WhoopsService.php ├── Whoops.php └── RenderExceptionWithWhoops.php ├── composer.json ├── readme.md └── LICENSE /config/config.php: -------------------------------------------------------------------------------- 1 | true, 6 | 7 | // 帮助您从异常堆栈跟踪中打开代码编辑器 8 | // 支持编辑器 sublime,textmate,emacs,macvim,phpstorm,idea,vscode,atom,espresso 9 | 'editor' => '', 10 | 11 | // 页面title提示 12 | 'title' => '发生内部错误,请稍后再试', 13 | ]; 14 | -------------------------------------------------------------------------------- /src/WhoopsService.php: -------------------------------------------------------------------------------- 1 | app->bind('whoops', Whoops::class); 14 | $this->app->bind('think\exception\Handle', RenderExceptionWithWhoops::class); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xiaodi/think-whoops", 3 | "description": "A debug service for ThinkPHP.", 4 | "authors": [ 5 | { 6 | "name": "xiaodi", 7 | "email": "liangjinbiao@live.com" 8 | } 9 | ], 10 | "keywords": [ 11 | "php", 12 | "thinkphp", 13 | "whoops" 14 | ], 15 | "license": "MIT", 16 | "type": "library", 17 | "require": { 18 | "php": ">=7.1.0", 19 | "topthink/framework": "6.0.*", 20 | "filp/whoops": "^2.4" 21 | }, 22 | "autoload": { 23 | "psr-4": { 24 | "think\\Whoops\\": "src" 25 | } 26 | }, 27 | "extra": { 28 | "think": { 29 | "services": [ 30 | "think\\Whoops\\WhoopsService" 31 | ], 32 | "config": { 33 | "whoops": "config/config.php" 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # think-whoops 2 | 3 | 让Whoops接管ThinkPHP6异常, Whoops提供stackbased错误捕获及超美观的错误 4 | 5 | [![Latest Stable Version](https://poser.pugx.org/xiaodi/think-whoops/version)](https://packagist.org/packages/xiaodi/think-whoops) 6 | [![Total Downloads](https://poser.pugx.org/xiaodi/think-whoops/downloads)](https://packagist.org/packages/xiaodi/think-whoops) 7 | [![License](https://poser.pugx.org/xiaodi/think-whoops/license)](https://packagist.org/packages/xiaodi/think-whoops) 8 | 9 | 10 | ## 安装 11 | ```php 12 | $ composer require xiaodi/think-whoops 13 | ``` 14 | 15 | ## 开启/关闭接管 16 | 开启 `APP_DEBUG` 才正常接管, 关闭默认转交ThinkPHP处理 17 | `config/whoops.php` 18 | ```php 19 | '', 17 | 'title' => '发生内部错误,请稍后再试', 18 | ]; 19 | 20 | public function __construct(Run $run) 21 | { 22 | $this->run = $run; 23 | $this->options = array_merge($this->options, config('whoops')); 24 | } 25 | 26 | public function __call($name, $arguments) 27 | { 28 | call_user_func_array([$this->run, $name], $arguments); 29 | } 30 | 31 | public function handleException($exception) 32 | { 33 | $handlers = $this->run->getHandlers(); 34 | 35 | foreach ($handlers as $handler) { 36 | if ($handler instanceof PrettyPageHandler) { 37 | $handler->addDataTable('ThinkPHP Application', [ 38 | 'Version' => App::VERSION, 39 | 'URI' => Request::url(true), 40 | 'Request URI' => Request::url(), 41 | 'Path Info' => Request::pathinfo(), 42 | 'Query String' => Request::query() ?: '', 43 | 'HTTP Method' => Request::method(), 44 | 'Base URL' => Request::baseUrl(), 45 | 'Scheme' => Request::scheme(), 46 | 'Port' => Request::port(), 47 | 'Host' => Request::host(), 48 | ]); 49 | 50 | // 从异常堆栈跟踪中打开代码编辑器 51 | if ($this->options['editor']) { 52 | $handler->setEditor($this->options['editor']); 53 | } 54 | 55 | // 设置标题 56 | $handler->setPageTitle($this->options['title']); 57 | } 58 | } 59 | 60 | $this->run->handleException($exception); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/RenderExceptionWithWhoops.php: -------------------------------------------------------------------------------- 1 | app->isDebug()) { 20 | if ($e instanceof HttpResponseException) { 21 | return $e->getResponse(); 22 | } 23 | 24 | // 兼容 Cors Postman 请求 25 | // $request->isAjax() 判断不太正常 26 | if ($request->isJson() || false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Postman') || (isset($_SERVER['HTTP_SEC_FETCH_MODE']) && $_SERVER['HTTP_SEC_FETCH_MODE'] === 'cors')) { 27 | return $this->handleAjaxException($e); 28 | } 29 | 30 | $this->app->whoops->pushHandler(new PrettyPageHandler()); 31 | 32 | return Response::create( 33 | $this->app->whoops->handleException($e), 34 | 'html', 35 | $e->getCode() 36 | ); 37 | } 38 | 39 | // 其他错误交给系统处理 40 | return parent::render($request, $e); 41 | } 42 | 43 | /** 44 | * 接管Ajax异常. 45 | * 46 | * @param Throwable $e 47 | * 48 | * @return void 49 | */ 50 | protected function handleAjaxException(Throwable $e) 51 | { 52 | $data = [ 53 | 'name' => get_class($e), 54 | 'file' => $e->getFile(), 55 | 'line' => $e->getLine(), 56 | 'message' => $this->getMessage($e), 57 | 'trace' => $e->getTrace(), 58 | 'code' => $this->getCode($e), 59 | 'source' => $this->getSourceCode($e), 60 | 'datas' => $this->getExtendData($e), 61 | 'tables' => [ 62 | 'GET Data' => $this->app->request->get(), 63 | 'POST Data' => $this->app->request->post(), 64 | 'Files' => $this->app->request->file(), 65 | 'Cookies' => $this->app->request->cookie(), 66 | 'Session' => $this->app->session->all(), 67 | 'Server/Request Data' => $this->app->request->server(), 68 | 'Environment Variables' => $this->app->request->env(), 69 | 'ThinkPHP Constants' => $this->getConst(), 70 | ], 71 | ]; 72 | 73 | $response = Response::create($data, 'json'); 74 | 75 | if ($e instanceof HttpException) { 76 | $statusCode = $e->getStatusCode(); 77 | $response->header($e->getHeaders()); 78 | } 79 | 80 | return $response->code($statusCode ?? 500); 81 | } 82 | } 83 | --------------------------------------------------------------------------------