You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从标记为monolog.processor的服务中获取Symfony路由参数

解决方案

你对问题原因的判断正确:Monolog处理器默认的执行时机早于Symfony路由解析流程,负责解析路由并将参数写入Request attributes的RouterListener内核监听器优先级为32,早于多数处理器触发时机,所以直接取值时路由参数还未写入。

以下是两种可行的解决方法:

方案1:绑定低优先级kernel.request事件预存路由参数(最稳妥)

该方案可以保证只要路由解析完成,参数就会提前存入处理器,所有后续日志都能稳定拿到用户ID:

第一步:改造UserProcessor代码

// src/Services/UserProcessor.php
use Monolog\Processor\ProcessorInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Event\RequestEvent;

final class UserProcessor implements ProcessorInterface
{
    private RequestStack $requestStack;
    private ?string $userId = null;

    public function __construct(RequestStack $requestStack)
    {
        $this->requestStack = $requestStack;
    }

    // 监听kernel.request事件的回调,路由解析完成后执行
    public function onKernelRequest(RequestEvent $event): void
    {
        if (!$event->isMasterRequest()) {
            return;
        }
        $request = $event->getRequest();
        // 从路由参数中取userid,不存在则留空
        if ($request->attributes->has('userid')) {
            $this->userId = $request->attributes->get('userid');
        }
    }

    public function __invoke(array $record): array
    {
        // 只有存在userId的时候才追加到日志上下文
        if ($this->userId !== null) {
            $record['extra']['user_id'] = $this->userId;
        }
        return $record;
    }
}

第二步:调整服务配置

在config/services.yaml中给服务同时加处理器和事件监听器标签,设置事件监听器优先级低于32,保证路由解析完成后再执行:

services:
    App\Services\UserProcessor:
        arguments:
            $requestStack: '@request_stack'
        tags:
            - { name: monolog.processor }
            - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 0 }

方案2:直接在处理器中做兼容判断(适合轻量场景)

如果你的日志只会在路由解析完成后触发,也可以直接在__invoke方法中做多层非空判断,避免报错:

public function __invoke(array $record): array
{
    $request = $this->requestStack->getMasterRequest();
    if (null !== $request && $request->attributes->has('userid')) {
        $record['extra']['user_id'] = $request->attributes->get('userid');
    }
    return $record;
}

注意:该方案下,路由解析完成前触发的日志(比如内核启动阶段的debug日志)仍然拿不到userid,业务接口请求阶段的日志不受影响。


额外注意事项

  • 要兼容CLI命令行场景,CLI下没有HTTP请求,getMasterRequest()会返回null,一定要做非空判断避免报错
  • Symfony 5+以上版本getMasterRequest()已废弃,替换为getMainRequest()即可

内容的提问来源于stack exchange,提问作者smarber

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 10:42:01