Webman多应用模式需同时满足两个硬性条件:app/下存在标准子应用目录(如app/admin),且config/app.php中必须显式配置applications数组,键名为URL路径前缀,值含controller_namespace,三者严格对齐才能触发应用级路由、中间件与异常处理。

Webman 多应用模式不是“开启”出来的,而是靠目录结构 + 配置显式声明出来的。没配置 config/app.php 里的 applications 键,即使你建了 app/admin 目录,框架也默认当它是普通子目录,不会识别为独立应用。
多应用模式依赖两个硬性条件
缺一不可:
-
app/下存在以目录形式组织的子应用(如app/api、app/admin),且各自包含controller/、config/等标准子目录 -
config/app.php中必须明确定义applications数组,每个键是应用名(如'api'),值是含controller_namespace的配置项
漏掉第二条,route.php 里写的 Route::get('/admin/xxx', [...]) 会直接走全局控制器解析逻辑,根本不会进 app/admin/controller。
应用名必须和 URL 路径前缀一致才能自动路由
Webman 不做路径猜测。它只在请求路径以某个应用名为前缀时,才启用该应用的命名空间和中间件:
立即学习“PHP免费学习笔记(深入)”;
- 访问
/api/users→ 自动匹配applications['api']配置 → 使用app\api\controller\UsersController - 访问
/admin/dashboard→ 自动匹配applications['admin']→ 使用app\admin\controller\DashboardController - 但访问
/v1/users却不会触发api应用,除非你在applications里额外配一个'v1'键,或改用显式路由绑定
也就是说:applications 的键名 = URL 路径第一段 = 控制器命名空间前缀,三者必须对齐,否则路由失效。
中间件和异常处理器按应用隔离,但需手动配
全局中间件(config/middleware.php 中键为 '' 的数组)对所有请求生效;而应用级中间件必须显式写进同个文件里对应应用名的键下:
return [
'' => [support\middleware\GlobalLog::class],
'api' => [support\middleware\Cors::class, support\middleware\RateLimit::class],
'admin' => [support\middleware\AdminAuth::class],
];
同样,config/exception.php 也得按应用名配 handler 类:
-
'api' => support\exception\ApiHandler::class→ 所有/api/下抛出的异常都走 JSON 返回 -
'admin' => support\exception\AdminHandler::class→ 渲染 HTML 错误页
不配,就 fallback 到全局 handler,容易导致 API 报错返回 HTML,前端解析失败。
public_path 和静态资源不随应用切换
public/ 始终是整个项目的唯一静态资源根目录,不存在 app/admin/public 这种结构。所有应用共用同一套 JS/CSS/图片,也共用同一个 config/app.php 里的 public_path 配置。
这意味着:
- 不能靠 URL 前缀区分静态资源(比如
/admin/logo.png和/api/logo.png实际指向同一个文件) - 如果真要隔离,得靠构建时重命名或加 hash,或在 Nginx 层做路径重写
这个限制常被忽略,直到上线后发现 admin 后台的 CSS 覆盖了 API 文档页的样式才反应过来。



















