TP6跨应用中间件冲突本质是执行顺序错位或作用域重叠:LoadLangPack默认优先级10,未设更低优先级的自定义中间件会滞后执行,导致$request->lang()为空;插件需独立注册中间件、小写短横线lang目录、加plugin_前缀Cookie,并在控制器前调Lang::set();Log::channel()无效因门面缓存,应改用Log::think()->setChannel()或每次new实例;Access-Control-Allow-Origin须动态读$origin而非$request->domain()。

TP6跨应用中间件冲突,本质是执行顺序错位或作用域重叠导致的逻辑覆盖。比如主站语言包加载完才执行插件中间件,或日志通道切换被后续中间件重置——不是配置写错了,而是时机没卡准。
中间件注册位置必须前置
全局中间件若想生效,得比 Session、Auth、LoadLangPack 更早执行。TP6 默认 LoadLangPack 优先级为 10,而多数自定义中间件未设 priority,默认为 0 或 null,实际反而更晚。结果就是:你的语言切换中间件执行时,$request->lang() 还是空的。
- 在
app/middleware.php中,把关键中间件(如多语言、CORS、插件初始化)放在数组最前面 - 类中间件可显式声明优先级:
protected $priority = 5;(数值越小越早) - 路由分组中挂载中间件时,也要确认是否覆盖了全局设置,例如
Route::group('plugin', ...)->middleware([PluginLangMiddleware::class])
插件与主站中间件需隔离上下文
插件语言包不会被主应用的 LoadLangPack 自动识别,强行复用会导致路径错乱、Cookie 冲突、翻译失效。
- 插件
lang/目录必须小写+短横线命名(如lang/zh-cn/common.php),不能是ZH-CN或zh_CN - 插件 Cookie 必须加唯一前缀(如
plugin_wechat_lang),避免和主站think_lang冲突 - 插件控制器执行前,必须手动调用
Lang::set('zh-cn'),不能依赖全局中间件“顺带”处理
日志通道切换要绕开门面缓存
Log::channel('zh') 在中间件里调用后依然写进 default.log,是因为 TP6 的 Log 门面在框架启动时已绑定默认实例,后续 channel() 只影响新生成的 logger,不影响已初始化的组件(如 SQL 日志、异常处理器)。
- 改用
Log::think()->setChannel('zh')(TP6.1+ 支持) - 或每次写日志都新建实例:
Log::channel('zh')->error('msg') - 确保
config/log.php中'default' => 'file',通道名只出现在channels配置里
动态 Origin 匹配别用 domain() 取值
跨域时 $request->domain() 返回的是当前服务端域名(如 b.cn),但 Access-Control-Allow-Origin 需返回前端发起请求的源(如 a.cn)。直接用它设头必然失败。
- 正确方式是读取请求头:
$origin = $request->header('origin') - 白名单校验必须基于完整协议+域名+端口:
https://admin.example.com,不是admin.example.com - 若需兼容子域名,可用
parse_url($origin, PHP_URL_HOST)提取 host 后模糊匹配(如endswith('.example.com'))

















