Webman默认不自动跳转404,需用Route::fallback()在config/route.php末尾显式定义;回调中须根据$request->expectsJson()区分AJAX/HTML,并分别调用json()->code(404)或view()->withStatus(404),确保HTTP状态码正确。

Webman 默认不自动跳转到 404 页面,未匹配路由会直接抛出 NotFoundException 并返回空白或简陋提示——这不是配置漏了,而是框架设计如此:它把“是否响应 404”这件事交给你显式决定。
Route::fallback 是最轻量、最推荐的兜底方式
这个方法不改异常处理器、不碰 Nginx 配置,只在路由层拦截所有未命中请求,适合绝大多数项目。
-
Route::fallback()必须放在config/route.php的最后(否则可能被前面的路由覆盖) - 回调函数接收
Request $request,可用$request->expectsJson()判断是否为 AJAX 请求 - 返回 JSON 时必须手动调用
json(...)->code(404),否则状态码默认是 200 - 返回视图时务必加
->withStatus(404),否则浏览器看到的是 200 状态码 + 404 内容,SEO 和调试都会出问题 - 确保
app/view/404.html存在且不含asset()、url()等可能在异常上下文中失效的辅助函数
Web 服务器伪静态没配对,根本进不了 fallback
如果你加了 Route::fallback() 却还是看到 Nginx 原生 404,说明请求压根没到达 PHP 层——这是 Web 服务器配置问题,不是代码问题。
- Nginx 必须用
try_files $uri $uri/ /public/index.php?$query_string;,不能只写rewrite - 检查
curl -I http://your-domain.com/any-path响应头里有没有X-Powered-By: Webman,没有就还在 Nginx 直返阶段 - Apache 用户需确认
.htaccess启用了RewriteEngine On,且规则包含RewriteRule ^(.*)$ public/index.php [L] - 若使用宝塔等面板,别只点“启用伪静态”,要手动打开配置文件核对
location /块内容
需要区分 404 和 405?升级到 Webman 1.5.23+
旧版本 fallback 回调只传 Request,无法知道是路径不存在(404)还是方法不支持(405)。1.5.23+ 支持第二个参数 $status,直接解耦处理逻辑。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
立即学习“PHP免费学习笔记(深入)”;
- 升级后回调签名变为
function(Request $request, int $status) -
$status === 404表示路由未定义;$status === 405表示方法不匹配(比如对Route::post()发 GET 请求) - 可共用一个 fallback,用数组映射不同状态的提示:
['404' => '页面不存在', '405' => '请求方式不被允许'] - 注意:该特性依赖框架底层支持,低版本即使写了第二个参数也不会被调用
为什么重写 Handler 不是首选?
它能统一处理所有异常(包括 500、403),但对 404 来说过于重型——你得新建类、注册配置、额外维护模板,还容易和 fallback 逻辑重复甚至冲突。
- Handler 适合中大型项目,当你要把 404/403/500 全部走同一套渲染逻辑时才值得投入
- 如果只为了 404,Handler 里还得额外判断
$e instanceof \support\exception\NotFoundException,比直接 fallback 多绕一层 - 一旦 Handler 的
render()方法本身出错(比如view('500')模板里引用了不存在的变量),就会二次崩溃,fallback 却不会 - 线上环境若开启调试模式,Handler 可能意外暴露敏感信息,fallback 更可控
真正容易被忽略的点是:404 页面自身不能依赖任何可能在异常链中已销毁的服务(如数据库连接、缓存实例、URL 生成器),否则它就成了新的故障点。最安全的做法,是让 404 模板纯静态,连 htmlspecialchars($error) 这种基础操作都手动做,而不是指望框架辅助函数一定可用。


















