不能。中间件中直接 new Service 会绕过容器,导致依赖无法解析;应通过构造函数注入AuthService,前提是中间件已注册进容器并实现MiddlewareInterface,且确保PSR-4路径与autoload生效。

中间件里能直接 new Service 吗?
不能。Service 类若依赖容器注入(比如用了 Request、Cache 或数据库连接),直接 new app\service\UserService() 会绕过容器,导致构造函数参数无法自动解析,抛出 ArgumentCountError 或返回空实例。
必须用 app()->make()?
可以,但不推荐。在中间件中调用 app()->make(\app\service\AuthService::class) 虽能拿到实例,但会破坏单例生命周期——尤其当 Service 内部持有请求上下文(如 $request->session())时,多个中间件并发执行可能共享错误的 session 数据。
- Service 默认是单例,但请求相关状态不能跨请求复用
- ThinkPHP 8.0+ 的容器在中间件阶段尚未完全 boot,部分服务(如日志、验证器)可能未就绪
- 更稳的方式是把 Service 注入到中间件类本身,靠框架自动 resolve
怎么让中间件正确使用 Service?
ThinkPHP 6.1+ 和 8.x 都支持中间件类的构造函数注入,前提是中间件已注册进容器(即通过 app/middleware.php 加载,且类名完整)。写法如下:
客服回复模板。售前咨询、售后处理、退换货、投诉回复、好评引导、升级处理、行业FAQ、满意度挽回。Customer service reply templates for pre-sale, after-sale, returns, complaints, escalation, FAQ generation, s...
namespace app\middleware;
use app\service\AuthService;
class AuthMiddleware
{
protected AuthService $authService;
public function __construct(AuthService $authService)
{
$this->authService = $authService;
}
public function handle($request, \Closure $next)
{
if (!$this->authService->checkToken($request->header('Authorization'))) {
return json(['code' => 401, 'msg' => 'Unauthorized']);
}
return $next($request);
}
}
- 确保
app/service/已在composer.json的psr-4中声明并运行过composer dump-autoload - 不要在
handle()里再调app()->make(),否则注入失效 - TP8 强制要求中间件实现
MiddlewareInterface,否则构造注入不触发
Service 里访问 Session 或 Request 安全吗?
不安全,除非你明确控制了执行时机。中间件早于 Session 初始化(如 SessionInit 中间件),此时 $request->session() 可能为 null 或报错。
立即学习“PHP免费学习笔记(深入)”;
- 优先用
$request->header()、$request->get()、$request->post()取原始数据 - 若必须查 session,确认该 Service 不被前置中间件(如
ForceHttps)调用,或手动触发:$request->session()->start() - API 场景建议 Token 校验走 Header,别依赖 session 文件驱动
真正容易被忽略的是:Service 的生命周期和中间件的执行顺序是绑定的,不是“写了就能用”,而是“注册位置决定它能不能拿到想要的对象”。


















