2016-04-21 16 views
5

Pracuję nad aplikacją Symfony 2.7 WebApp. Jeden z utworzonych przeze mnie pakietów obejmuje usługę, która oferuje pewne rzeczy związane z użytkownikami, np. userHasPurchases().Rozszerzenie Symfony Twig narusza inne usługi - Czy szablon jest wykonywany przed bezpieczeństwem?

Problem w tym, że w tym Twig Extesion przerwy kolejna usługa:

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" 
      - ... 

Jak dotąd wszystko działa dobrze: The AppShopServices jest tworzony z bieżącym użytkownikiem i userHasPurchases() działa zgodnie z oczekiwaniami.

Teraz muszę dodać Gałązka Extension, aby móc korzystać z userHasPurchases() zasięgu moich szablonów:

Gałązka Extension

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); 
    } 
} 

tym rozbudowa w 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 } 

Po włączeniu Twig Extension, AppShopService i jego metoda userHasPurchases nie działa. Problem polega na tym, że konstruktor AppShopService nie ustawia już wartości user, ponieważ $tokenStorage->getToken() teraz zwraca null.

Jak to jest możliwe? Nie zmieniłem nic, z wyjątkiem Twig Extension. Po usunięciu Twig Extension z services.yml wszystko znów działa poprawnie.

Moim jedynym przypuszczeniem jest, że tworzenie Twig Extension odbywa się przed każdym zabezpieczeniem. Ale dlaczego?

Każdy pomysł, co może być nie tak?

+1

W ogóle, nie chcesz, aby użytkownik w konstruktorze. Nigdy nie wiadomo, czy komponent bezpieczeństwa zrobił to, zanim obiekt zostanie utworzony. Więc po prostu dodaj MyService :: getUser i wywołaj go, gdy będzie to potrzebne. Oszczędź sobie chwilowych bólów głowy. – Cerad

+1

nie wchodzić w interakcje z tokenStorage w konstruktorze, ale tylko w metodzie 'userHasPurchases'' – Matteo

Odpowiedz

3

nie wchodzą w interakcje z tokenStorage w konstruktorze, ale tylko w metodzie 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; 
    } 
} 

Nadzieja ta pomoc

+0

Wielkie dzięki! To faktycznie rozwiązuje problem. Ale dlaczego? Rozumiem, że czas może być problemem, ale czy bezpieczeństwo/szablony/etc wykonane asynchronicznie? Używam '$ this-> user = $ this-> tokenStorage-> getToken()? $ this-> tokenStorage-> getToken() -> getUser(): null; 'również w kilku innych usługach, bez żadnego problemu. Co jest takiego specjalnego w tym przypadku? –

+0

Witaj @AndreiHerford to zależy od cyklu życia usługi, ale nie znajduję w tej chwili żadnych zasobów na ten temat.Zazwyczaj wchodzę w interakcję z usługą tylko wtedy, gdy jej potrzebuję i nigdy w konstruktorze samej usługi, więc usługa może być bezstanowa (należy unikać atrybutu "Zmienna"). Mam nadzieję, że to pomoże – Matteo