跳转到主要内容

什么是 Context

Laravel 的 Context 功能提供了一种在请求、队列任务、命令之间跨越执行边界记录与共享信息的机制。 通过 Illuminate\Support\Facades\Context 门面添加的信息,会自动附带到应用写出的所有日志条目中。 这样就能明确区分某次日志调用附带的信息与 Context 保存的共享信息。 在使用队列或分布式架构进行追踪时尤其有用。

上下文的传播流程

基本用法

最典型的用法是在中间件中设置 trace_id。之后所有的日志都会自动包含它。
1

创建中间件

2

向 Context 添加追踪 ID

3

注册中间件

bootstrap/app.php 中作为全局中间件注册。
配置好后,控制器或服务写入的日志会自动附带 urltrace_id

写入上下文

add — 添加值

add 会覆盖已有的键。若只想在键不存在时才添加,使用 addIf

increment / decrement — 管理计数器

用于数值增减的专用方法,可通过第二个参数指定增减量。

when — 按条件添加

使用 when 可以根据条件为 truefalse 分别添加不同的数据。

push — 追加到栈

Context 支持以「栈」的形式保存列表数据。 push 会按添加顺序累积数据。
以下是把查询执行历史存入栈的示例:

读取上下文

get / all

only / except — 获取子集

pull / pop — 取出并删除

pull 在取值的同时从上下文中删除该键。
从栈中取出最后一个值使用 pop

remember — 不存在则设置并返回

has / missing — 判断键是否存在

即使存的是 nullhas 也会返回 true。它只判断键是否已注册。

删除上下文

使用 forget 删除键。

作用域上下文

使用 scope 可以在闭包执行期间临时修改上下文,闭包结束后自动恢复原状态。 在测试或局部处理中希望暂时向日志中附加信息时非常方便。
在 scope 内修改了对象的话,该修改在 scope 外也会保留。使用基本类型时不会有此问题。

Hidden Context

对于不希望输出到日志的数据(密码、API 密钥、个人识别信息等),可存放到 Hidden Context 中。 普通的 get 无法读取,需通过 getHidden 等专用方法访问。
Hidden Context 提供与普通 Context 一致的方法集:

传递到队列任务

当把任务派发到队列时,当前的上下文会自动序列化并包含在任务的 payload 中。 任务执行时会恢复原上下文,因此请求中设置的 trace_id 也会自动出现在队列中的日志里。
可以看到请求中的 trace_id 也出现在了队列上的日志中。

Dehydrating — 任务发送时的自定义

Context::dehydrating 允许在任务发送前修改上下文。 比如,可用于把由 Accept-Language 头决定的 locale 传给队列。
dehydrating 回调中请不要使用 Context 门面,而是操作回调传入的 $context 仓库。 使用门面会修改当前进程的上下文。

Hydrated — 任务执行时的恢复

Context::hydrated 用于在任务执行前恢复上下文的时机添加处理。 比如,把此前保存的 locale 应用回配置:
hydrated 回调中同样不要使用 Context 门面,只操作传入的 $context 仓库。

小结

Hidden Context 不会输出到日志,因此适合安全地存放:
  • 会话 ID 或用户 ID(不希望进日志时)
  • API 密钥或认证令牌
  • locale 或配置项(需要传递给队列但不需要出现在日志中)
  • 内部标志或状态
  1. locale 传递dehydrating 时把 app.locale 存入 Hidden Context,hydrated 时通过 Config::set 恢复。
  2. 认证信息传播:使队列任务也能访问请求时已认证的用户信息。
  3. 租户 ID:在多租户应用中跨队列共享租户标识。
最后修改于 2026年7月18日