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

TokenStorageInterface注入订阅者调用的服务后始终返回空问题咨询

问题原因
  • 实例化时机错误:Symfony 的事件订阅者会在容器初始化阶段就完成实例化,你在 OverridesSubscriber 的构造函数中直接调用 RestaurantService::getRestaurantId() 时,安全认证流程还未执行,TokenStorage 中还没有写入登录用户的 Token,要么返回 null 要么返回未完成认证的 Token。
  • 类型判断逻辑错误:TokenStorageInterface::getToken() 返回的是 Symfony\Component\Security\Core\Authentication\Token\TokenInterface 接口的实现对象,或者未认证时返回 null,永远不会直接返回 User 实例,需要调用 Token 对象的 getUser() 方法才能拿到关联的用户对象,所以原有的类型判断本身就不成立,必然永远返回 false。
解决方法
  • 首先修正 RestaurantService 中的用户判断逻辑:
public function getRestaurantId(): ?int
{
    $token = $this->tokenStorage->getToken();
    // 依次校验Token存在、已完成认证、用户类型符合要求
    if (!$token || !$token->isAuthenticated() || !($user = $token->getUser()) instanceof User) {
        return null; // 未登录场景可根据业务需求返回默认值或抛出异常
    }
    // 后续获取用户关联restaurantId的业务逻辑
}
  • 调整事件订阅者的逻辑执行时机,不要在构造函数中执行业务逻辑,改为在对应事件的回调方法中调用:
class OverridesSubscriber implements EventSubscriberInterface
{
    private RestaurantService $restaurantService;

    // 构造函数仅做依赖注入,不执行任何需要运行时上下文的业务逻辑
    public function __construct(RestaurantService $restaurantService)
    {
        $this->restaurantService = $restaurantService;
    }

    // 在监听的事件回调方法中执行获取商户ID的逻辑
    public function onTargetEvent(TargetEventClass $event)
    {
        $restaurantId = $this->restaurantService->getRestaurantId();
        // 后续业务逻辑处理
    }

    public static function getSubscribedEvents()
    {
        // 保留你原有事件配置,注意选择安全认证流程完成后才触发的事件
        return [
            TargetEventClass::class => 'onTargetEvent',
        ];
    }
}
  • 额外注意:如果监听的是请求类事件,需要确保监听优先级低于安全防火墙的处理优先级,避免在认证流程完成前就执行逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 08:54:07