2012-04-03 15 views
37

मैं वर्तमान में लॉग इन उपयोगकर्ता को किसी सेवा में इंजेक्ट करने का प्रयास कर रहा हूं। मेरा लक्ष्य उपयोगकर्ता प्राथमिकताओं के आधार पर इसे आउटपुट करने के लिए कुछ जुड़वां कार्यक्षमता का विस्तार करना है। इस उदाहरण में मैं उपयोगकर्ता विशिष्ट टाइमज़ोन का उपयोग कर किसी भी दिनांक फ़ंक्शन को आउटपुट करना चाहता हूं।Symfony2: सेवा में वर्तमान उपयोगकर्ता इंजेक्ट करें

वर्तमान उपयोगकर्ता को किसी सेवा में इंजेक्ट करने का कोई तरीका नहीं प्रतीत होता है, जो वास्तव में मेरे लिए अजीब लगता है। सुरक्षा संदर्भ इंजेक्शन करते समय, उपयोगकर्ता को

में लॉग इन किया गया है, तो भी यह टोकन नहीं है, मैं एफओएस उपयोगकर्ता बंडल का उपयोग कर रहा हूं।

services: 
    ... 
    twigdate.listener.request: 
     class: App\AppBundle\Services\TwigDateRequestListener 
     arguments: [@twig, @security.context] 
     tags: 
      - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest } 


<?php 

namespace App\AppBundle\Services; 

use Symfony\Component\HttpKernel\HttpKernelInterface; 
use Symfony\Component\HttpKernel\Event\GetResponseEvent; 

class TwigDateRequestListener 
{ 
    protected $twig; 

    function __construct(\Twig_Environment $twig, SecurityContext $context) { 

     $this->twig = $twig; 
     //$this->user = $context->get...; 

     var_dump($context); die; 
    } 

    public function onKernelRequest(GetResponseEvent $event) { 
     // $this->twig->getExtension('core')->setDateFormat($user->getProfile()->getFormat()); 
     // $this->twig->getExtension('core')->setTimeZone($user->getProfile()->getTimezone()); 
    } 
} 

output: 

object(Symfony\Component\Security\Core\SecurityContext)[325] 
    private 'token' => null 
    private 'accessDecisionManager' => 
    object(Symfony\Component\Security\Core\Authorization\AccessDecisionManager)[150] 
     private 'voters' => 
     array 
      0 => 
      object(Symfony\Component\Security\Core\Authorization\Voter\RoleHierarchyVoter)[151] 
       ... 
      1 => 
      object(Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter)[153] 
       ... 
      2 => 
      object(Symfony\Component\Security\Acl\Voter\AclVoter)[155] 
       ... 
     private 'strategy' => string 'decideAffirmative' (length=17) 
     private 'allowIfAllAbstainDecisions' => boolean false 
     private 'allowIfEqualGrantedDeniedDecisions' => boolean true 
    private 'authenticationManager' => 
    object(Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager)[324] 
     private 'providers' => 
     array 
      0 => 
      object(Symfony\Component\Security\Core\Authentication\Provider\DaoAuthenticationProvider)[323] 
       ... 
      1 => 
      object(Symfony\Component\Security\Core\Authentication\Provider\AnonymousAuthenticationProvider)[149] 
       ... 
     private 'eraseCredentials' => boolean true 
    private 'alwaysAuthenticate' => boolean false 

क्या मुझे कुछ याद आ रही है?

उत्तर

41

मुझे लगता है कि के लिए एक टहनी विस्तार का प्रयोग करेंगे:

class UserDateExtension extends \Twig_Extension 
{ 
    private $context; 

    public function __construct(SecurityContext $context) 
    { 
     $this->context = $context; 
    } 

    public function getUser() 
    { 
     return $this->context->getToken()->getUser(); 
    } 

    public function getFilters() 
    { 
     return array(
      'user_date' => new \Twig_Filter_Method($this, "formatUserDate"), 
     ); 
    } 

    public function formatUserDate($date, $format) 
    { 
     $user = $this->getUser(); 
     // do stuff 
    } 
अब

services.xml

<service id="user_date_twig_extension" class="%user_date_twig_extension.class%"> 
     <tag name="twig.extension" /> 
     <argument type="service" id="security.context" /> 
    </service> 

में फिर टहनी में तुम कर सकते हो:

{{ date | user_date('d/m/Y') }} 
+0

धन्यवाद यह पूरी तरह से काम किया। मुझे अभी भी समझ में नहीं आता कि मेरा पहला उदाहरण उपयोगकर्ता ऑब्जेक्ट क्यों नहीं लौटा, लेकिन मुझे यह काम मिल गया, और मुझे लगता है कि एक ट्विग एक्सटेंशन वास्तव में एक क्लीनर दृष्टिकोण है। त्वरित उत्तर – n0xie

+2

के लिए धन्यवाद ठीक है आप 'kernel.request' ईवेंट के लिए सुन रहे थे। प्रमाणन द्वारा संदर्भ टोकन सेट करना या सत्र से टोकन पढ़ने के बाद सभी 'kernel.request' श्रोताओं को प्रेषित किया जाता है। अगर आपने 'kernel.response' ईवेंट के लिए सुनी है तो आपको वांछित टोकन मिल जाएगा। अपने प्रश्न को गलत तरीके से मिटाने के लिए भी खेद है। यह मेरे लिए एक बुरा दिन है :)। –

+0

यह समझ में आता है। स्पष्टीकरण के लिए धन्यवाद। आप हर रोज कुछ न कुछ सीखते हैं। – n0xie

-9

आप @service_container इंजेक्शन करने का प्रयास कर सकते हैं और $this->container->get('security.context')->getToken()->getUser(); कर सकते हैं।

+26

पूरे कंटेनर इंजेक्शन अधिकांश में एक बुरा विचार है मामलों। इसके बजाय आपको प्रत्येक सेवा को इंजेक्ट करना चाहिए जिसे आपको स्पष्ट रूप से चाहिए। –

+0

@ एलनूर, इसे बताएं [फ्रेंड्सऑफसिम्फनी] (https://github.com/FriendsOfSymfony/FOSFacebookBundle/blob/master/Twig/Extension/FacebookExtension.php#L26) :) –

+2

ट्विग एक्सटेंशन इस नियम के अपवादों में से एक है । –

4

उपयोगकर्ता एक बुरी उम्मीदवार एक सेवा बनने के लिए।

  • पहले यह एक मॉडल सेवा नहीं है
  • दूसरा security.context सेवा जहां से उपयोगकर्ता प्राप्त कर सकते हैं नहीं है।

एक ट्वेंग टेम्पलेट में आप app.user का उपयोग कर सकते हैं। सिम्फनी डॉक्टर global-template-variables देखें। यदि आप उपयोगकर्ता अनुमतियों के आधार पर कुछ दिखाना चाहते हैं तो आप {{is_granted ('ROLE_USER')}} कर सकते हैं।

56

मुझे लगता है कि यह प्रश्न नए सुरक्षा घटक सुधारों के बाद से 2.6.x + के बाद से एक अद्यतन उत्तर का हकदार है।

use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; 

class UserDateExtension extends \Twig_Extension 
{ 
    /** 
    * @var TokenStorage 
    */ 
    protected $tokenStorage; 


    /** 
    * @param \Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage $tokenStorage 
    */ 
    public function __construct(TokenStorage $tokenStorage) 
    { 
     $this->tokenStorage = $tokenStorage; 
    } 

    public function getUser() 
    { 
     return $this->tokenStorage->getToken()->getUser(); 
    } 

    public function getFilters() 
    { 
     return array(
      'user_date' => new \Twig_Filter_Method($this, "formatUserDate"), 
     ); 
    } 

    public function formatUserDate($date, $format) 
    { 
     $user = $this->getUser(); 
     // do stuff 
    } 
} 

Services.yml

twig.date_extension: 
    class: Acme\Twig\SpecialDateExtension 
    tags: 
     - { name: twig.extension } 
    arguments: 
     - "@security.token_storage" 
1

मैं एक अलग घटना बंधन की सिफारिश करेंगे, अगर आप kernel.controller घटना का उपयोग करें, आप एक टोकन है और कोई समस्या नहीं होगा। टोकन में kernel.requestSymfony 2.3 के बाद से

मैं कैसे अपने ब्लॉग Symfony 2.6+ User Timezones कहा जाता है पर Symfony 2.3+ और टहनी में 2.6+ के लिए उपयोगकर्ता समय क्षेत्र को लागू करने पर एक गाइड लिखा उपलब्ध नहीं है।

यह एक ट्विग एक्सटेंशन का उपयोग करने के लिए काफी बेहतर है क्योंकि आप ट्विग में मानक दिनांक स्वरूपण फ़ंक्शंस का उपयोग कर सकते हैं, साथ ही अलग बैकएंड यूटीसी दिनांक, डिफ़ॉल्ट ट्विग डेट टाइमज़ोन और उपयोगकर्ता परिभाषित ट्विग डेट टाइमज़ोन प्रदान कर सकते हैं।

src/AppBundle/EventListener/TwigSubscriber:

यहाँ सबसे महत्वपूर्ण अंश है।php

<?php 

namespace AppBundle\EventListener; 

use AppBundle\Entity\User; 
use Symfony\Component\EventDispatcher\EventSubscriberInterface; 
use Symfony\Component\HttpKernel\Event\FilterControllerEvent; 
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; 

class TwigSubscriber implements EventSubscriberInterface 
{ 
    protected $twig; 
    protected $tokenStorage; 

    function __construct(\Twig_Environment $twig, TokenStorageInterface $tokenStorage) 
    { 
     $this->twig = $twig; 
     $this->tokenStorage = $tokenStorage; 
    } 

    public static function getSubscribedEvents() 
    { 
     return [ 
      'kernel.controller' => 'onKernelController' 
     ]; 
    } 

    public function onKernelController(FilterControllerEvent $event) 
    { 
     $token = $this->tokenStorage->getToken(); 

     if ($token !== null) { 
      $user = $token->getUser(); 

      if ($user instanceof User) { 
       $timezone = $user->getTimezone(); 
       if ($timezone !== null) { 
        $this->twig->getExtension('core')->setTimezone($timezone); 
       } 
      } 
     } 
    } 
} 

अब आप और सामान्य रूप टहनी उपयोग कर सकते हैं इसे अपने उपयोगकर्ता वरीयताओं का उपयोग करता है यदि उपलब्ध है।

29

services.yml

my_service: 
    class: ... 
    arguments: 
     - "@=service('security.token_storage').getToken().getUser()" 

Service.php

protected $currentUser; 

public function __construct($user) 
{ 
    $this->currentUser = $user; 
} 

http://symfony.com/doc/current/book/service_container.html#using-the-expression-language

+2

यह सबसे अच्छा जवाब है 2016 symfony 2.6 और ऊपर – 10us

+10

के लिए यह सुरक्षा फ़ायरवॉल के बाहर काम करता है? मेरा मतलब है, क्या यह "शून्य" लौटाता है या क्या यह अपवाद फेंकता है क्योंकि getToken() शून्य देता है और -> getUser() को शून्य ऑब्जेक्ट पर लागू नहीं किया जा सकता है? –

+1

सिम्फनी 3.2 – Londeren

2

Symfony 2.6 से।

आप का उपयोग @ security.token_storage

use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; 

class UserDateExtension extends \Twig_Extension 
{ 
/** 
* @var TokenStorageInterface 
*/ 
protected $tokenStorage; 


/** 
* @param $tokenStorage TokenStorage 
*/ 
public function __construct(TokenStorage $tokenStorage) 
{ 
    $this->tokenStorage = $tokenStorage; 
} 

public function getUser() 
{ 
    return $this->tokenStorage->getToken()->getUser(); 
} 

public function getFilters() 
{ 
    return array(
     'user_date' => new \Twig_Filter_Method($this, "formatUserDate"), 
    ); 
} 

public function formatUserDate($date, $format) 
{ 
    $user = $this->getUser(); 
    // do stuff 
} 

}

और Services.yml

twig.date_extension: 
    class: Acme\Twig\SpecialDateExtension 
    tags: 
     - { name: twig.extension } 
    arguments: ["@security.token_storage"] 

संदर्भ की जरूरत है: http://symfony.com/blog/new-in-symfony-2-6-security-component-improvements

संबंधित मुद्दे