2016-04-21 26 views
5

Sto lavorando su una WebApp di Symfony 2.7. Uno dei bundle che ho creato include un servizio che offre alcune informazioni relative all'utente, ad es. userHasPurchases().Symfony Twig Extension interrompe altri servizi: la templatura viene eseguita prima della sicurezza?

Il problema è, che tra cui un Twig Extesion rompe un altro servizio:

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

Finora tutto funziona bene: il AppShopServices viene creato con l'utente corrente e userHasPurchases() funziona come previsto.

Ora ho aggiungere un Twig Extensionper essere in grado di utilizzare userHasPurchases() entro miei modelli:

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

inclusa l'estensione a 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 } 

Dopo aver ignorato il Twig Extension, AppShopService e il suo metodo userHasPurchases non funziona più. Il problema è che il costruttore di AppShopService non imposta più user dal $tokenStorage->getToken() ora restituisce null.

Com'è possibile? Non ho cambiato nulla tranne l'inclusione dello Twig Extension. Non appena rimuovo lo Twig Extension da services.yml, tutto funziona di nuovo correttamente.

La mia unica ipotesi è che la creazione per lo Twig Extension venga eseguita prima di qualsiasi sicurezza. Ma perché?

Qualche idea di cosa potrebbe esserci di sbagliato qui?

+1

In generale, non si vuole ottenere l'utente nel costruttore. Non sai mai se il componente di sicurezza ha funzionato prima che il tuo oggetto sia creato. Quindi aggiungi un MyService :: getUser e chiamalo quando è necessario. Salva te stesso alcuni mal di testa di temporizzazione. – Cerad

+1

non interagire con tokenStorage nel costruttore ma solo nel metodo 'userHasPurchases'' – Matteo

risposta

3

non interagiscono con tokenStorage nel costruttore ma solo nel metodo 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; 
    } 
} 

Spero che questo aiuto

+0

Grazie mille! Questo in effetti risolve il problema. Ma perché? Capisco che il tempismo può essere un problema, ma la sicurezza/i template/etc sono sincronizzati? Io uso '$ this-> user = $ this-> tokenStorage-> getToken()? $ this-> tokenStorage-> getToken() -> getUser(): null; 'anche in molti altri servizi, senza alcun problema fino ad ora. Cosa c'è di così speciale in questo caso? –

+0

hi @AndreiHerford dipende dal ciclo di vita del servizio ma al momento non trovo risorse al riguardo.Di solito interagisco con il servizio solo quando ne ho bisogno, e mai nel costruttore del servizio stesso, quindi il servizio può essere stateless (evitare l'attributo di chiamata mutabile). Spero che questo aiuto – Matteo