【问题标题】:Symfony Twig Extension breaks other service - Is templating done before security?Symfony Twig Extension 破坏了其他服务 - 模板是在安全之前完成的吗?
【发布时间】:2016-04-21 12:05:42
【问题描述】:

我正在开发一个 Symfony 2.7 WebApp。我创建的其中一个捆绑包包括一项提供一些与用户相关的东西的服务,例如userHasPurchases().

问题是,包含Twig Extesion 会破坏另一个服务:

AppShopService

namespace AppShopBundle\Service;

use AppBundle\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
...

class AppShopService {
    protected $user;

    public function __construct(TokenStorageInterface $tokenStorage, ...) {
        $this->user = $tokenStorage->getToken() ? $tokenStorage->getToken()->getUser() : null;
        ...
    }

    public function userHasPurchases(User $user) {
        $user = $user ? $user : $this->user;
        $result = $user...
        return result;
    }
}

AppShopBundle\Resources\config\services.yml

services:
    app_shop.service:
        class: AppShopBundle\Service\AppShopService
        arguments: 
            - "@security.token_storage"
            - ...

到目前为止一切正常:AppShopServices 是使用当前用户创建的,userHasPurchases() 按预期工作。

现在我添加了一个 Twig 扩展,以便能够在我的模板中使用 userHasPurchases()

树枝扩展

namespace AppShopBundle\Twig;

use AppShopBundle\Service\AppShopService;

class AppShopExtension extends \Twig_Extension {
    private $shopService;

    public function __construct(AppShopService $shopService) {
        $this->shopService = $shopService;
    }

    public function getName() {
        return 'app_shop_bundle_extension';
    }

    public function getFunctions() {
        $functions = array();

        $functions[] = new \Twig_SimpleFunction('userHasPurchases', array(
                $this,
                'userHasPurchases'
            ));

        return $functions;
    }

    public function userHasPurchases($user) {
        return $this->shopService->userHasPurchases($user);
    }
}

在 AppShopBundle\Resources\config\services.yml 中包含扩展

services:
    app_shop.service:
        class: AppShopBundle\Service\AppShopService
        arguments: 
            - "@security.token_storage"
            - ...

    app_shop.twig_extension:
        class: AppShopBundle\Twig\AppShopExtension
        arguments: 
          - "@app_shop.service"
        tags:
          - { name: twig.extension }

在包含Twig ExtensionAppShopService 及其方法userHasPurchases 后不再起作用。问题是,AppShopService 的构造函数不再设置user,因为$tokenStorage->getToken() 现在返回null

这怎么可能?除了Twig Extension,我什么都没改变。一旦我从services.yml 中删除Twig Extension,一切都会再次正常工作。

我唯一的猜测是,Twig Extension 的创建是在任何安全性之前完成的。但为什么呢?

知道这里可能出了什么问题吗?

【问题讨论】:

  • 一般来说,你不希望在构造函数中获取用户。在创建对象之前,您永远不会真正知道安全组件是否已经完成了它。所以只需添加一个 MyService::getUser 并在需要时调用它。省去一些时间上的麻烦。
  • 不要在构造函数中与 tokenStorage 交互,而只能在 `userHasPurchases`` 方法中交互

标签: php symfony twig twig-extension


【解决方案1】:

不要在构造函数中与 tokenStorage 交互,而只能在 userHasPurchases 方法中。

namespace AppShopBundle\Service;

use AppBundle\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
...

class AppShopService {
    protected $tokenStorage;

    public function __construct(TokenStorageInterface $tokenStorage, ...) {
        $this->tokenStorage = $tokenStorage;
    }

    public function userHasPurchases(User $user) {
        $user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null;
        $result = $user...
        return result;
    }
}

希望有帮助

【讨论】:

  • 非常感谢!这确实解决了问题。但为什么?我知道时间可能是一个问题,但是安全/模板/等是否异步完成?我也在其他几个服务中使用$this->user =$this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null;,到目前为止没有任何问题。在这种情况下有什么特别之处?
  • 嗨@AndreiHerford 这取决于服务的生命周期,但我目前没有找到任何关于它的资源。通常我只在需要时才与服务交互,而不是在服务本身的构造函数中进行交互,因此服务可以是无状态的(避免可变调用属性)。希望对您有所帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-27
  • 2016-08-28
相关资源
最近更新 更多