Расширение Symfony Twig прерывает работу других сервисов. Выполняется ли создание шаблонов до обеспечения безопасности?

Я работаю над веб-приложением Symfony 2.7. Один из созданных мной пакетов включает в себя сервис, который предлагает некоторые вещи, связанные с пользователем, например. userHasPurchases().

Проблема в том, что включение Twig Extesion ломает другой сервис:

Сервис AppShop

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() в своих шаблонах:

Расширение Twig

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 Extension, AppShopService и его метода userHasPurchases больше не работает. Проблема в том, что конструктор AppShopService больше не устанавливает user, так как $tokenStorage->getToken() теперь возвращает null.

Как это возможно? Я ничего не менял, кроме включения Twig Extension. Как только я удаляю Twig Extension из services.yml все снова работает правильно.

Мое единственное предположение состоит в том, что создание Twig Extension выполняется до какой-либо безопасности. Но почему?

Есть идеи, что здесь может быть не так?


person Andrei Herford    schedule 21.04.2016    source источник
comment
В общем, вы не хотите, чтобы пользователь был в конструкторе. Вы никогда не знаете, сделал ли компонент безопасности свое дело до того, как ваш объект будет создан. Так что просто добавьте MyService::getUser и вызывайте его всякий раз, когда это необходимо. Избавьте себя от головной боли, связанной со временем.   -  person Cerad    schedule 21.04.2016
comment
не взаимодействуйте с tokenStorage в конструкторе, а только в методе `userHasPurchases``   -  person Matteo    schedule 21.04.2016


Ответы (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;
    }
}

Надеюсь, это поможет

person Matteo    schedule 21.04.2016
comment
Большое спасибо! Это действительно решает проблему. Но почему? Я понимаю, что время может быть проблемой, но безопасность/шаблоны/и т. д. выполняются асинхронно? Я также использую $this->user =$this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null; в нескольких других сервисах, пока без проблем. Что в этом случае особенного? - person Andrei Herford; 21.04.2016
comment
привет @AndreiHerford, это зависит от жизненного цикла службы, но на данный момент я не нахожу никаких ресурсов по этому поводу. Обычно я взаимодействую со службой только тогда, когда она мне нужна, и никогда в конструкторе самой службы, поэтому служба может быть без состояния (избегайте изменяемого атрибута вызова). Надеюсь, это поможет - person Matteo; 21.04.2016