hyperf 默认不渲染 html 错误页,需手动实现开发环境可视化异常页:通过注册 devexceptionpagemiddleware 中间件捕获异常并用 view 渲染 blade 模板,同时确保视图路径配置正确、禁用开发环境的异常处理器冲突,并在生产环境复用模板渲染静态错误页。

Hyperf 默认不渲染 HTML 错误页,而是返回 JSON 或纯文本响应。若需像 Laravel 那样在开发环境显示带堆栈、上下文的可视化错误页面(如“开发人员异常页”),Hyperf 本身不内置该功能,但可通过组合中间件 + 自定义异常处理器 + 视图组件实现近似效果——关键在于不依赖框架默认兜底,而主动接管 HTTP 响应体为 HTML 内容。
启用开发环境错误页面需手动构建
Hyperf 没有 UseDeveloperExceptionPage 这类开箱即用的中间件,但你可以通过以下方式模拟:
- 在
config/autoload/middlewares.php中注册一个全局中间件,仅在APP_ENV=dev下生效 - 该中间件捕获未被异常处理器吞掉的
Throwable,并用 View 组件渲染带堆栈的 Blade/Twig 模板 - 注意:必须确保 View 组件已正确安装且
storage.path可写(否则模板编译失败导致白屏)
// app/Middleware/DevExceptionPageMiddleware.php
<?php namespace App\Middleware;
use Hyperf\HttpServer\Contract\ResponseInterface;
use Hyperf\HttpServer\Response;
use Hyperf\View\RenderInterface;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface as PsrResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
class DevExceptionPageMiddleware implements MiddlewareInterface
{
public function __construct(
private ContainerInterface $container,
private RenderInterface $view
) {}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): PsrResponseInterface
{
try {
return $handler->handle($request);
} catch (\Throwable $e) {
if (env('APP_ENV') !== 'dev') {
throw $e; // 非开发环境继续抛出,交由异常处理器处理
}
$response = $this->container->get(ResponseInterface::class);
return $response->html(
$this->view->render('errors/developer', [
'exception' => $e,
'trace' => $e->getTraceAsString(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'message' => $e->getMessage(),
]),
500
);
}
}
}
再在 config/autoload/middlewares.php 中注册:
return [
'http' => [
\App\Middleware\DevExceptionPageMiddleware::class,
// 其他中间件...
],
];
准备视图模板 resources/views/errors/developer.blade.php
<title>Development Exception</title><style>
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto; margin: 2rem; }
.error-header { color: #d32f2f; font-size: 1.5rem; }
.trace { background: #f5f5f5; padding: 1rem; overflow-x: auto; }
.file-line { color: #1976d2; font-weight: bold; }
</style><h1 class="error-header">Uncaught Exception</h1>
<p><strong>{{ $message }}</strong></p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill4029" title="Hyperframes Creative"><img
src="https://img.php.cn/upload/skill/000/000/081/178988960574411.jpg" alt="Hyperframes Creative" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill4029" title="Hyperframes Creative" class="overflowclass">Hyperframes Creative</a>
<p class="overflowclass">HyperFrames视频非动画创意指导,包括设计规范(frame.md/design.md)处理、配色、字体设计、旁白及节奏规划等。</p>
</div>
<a rel="nofollow" href="/xiazai/skill4029" title="Hyperframes Creative" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<p class="file-line">{{ $file }}:{{ $line }}</p>
<div class="trace"><pre class="brush:php;toolbar:false;">{{ $trace }}










