2017-11-15 20 views
6

Theo câu hỏi này How to load Symfony's config parameters from database (Doctrine) Tôi có vấn đề tương tự. Tôi cần đặt tham số động và tôi muốn cung cấp dữ liệu từ một dịch vụ tùy chỉnh khác.Tải thông số của Symfony bằng trình biên dịch chuyển từ dịch vụ tùy chỉnh

Vì vậy, tôi có nghe sự kiện mà thiết thực thể tài khoản vãng lai (bởi sub-domain ngừơi tiêu dùng hiện đang đăng nhập)

namespace AppBundle\EventListener; 

use Symfony\Component\HttpKernel\Event\GetResponseEvent; 
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; 
use Doctrine\ORM\EntityManager; 
use AppBundle\Manager\AccountManager; 

use Palma\UserBundle\Entity\User; 

/** 
* Class CurrentAccountListener 
* 
* @package AppBundle\EventListener 
*/ 
class CurrentAccountListener { 

    /** 
    * @var TokenStorage 
    */ 
    private $tokenStorage; 

    /** 
    * @var EntityManager 
    */ 
    private $em; 

    /** 
    * @var AccountManager 
    */ 
    private $accountManager; 

    private $baseHost; 

    public function __construct(TokenStorage $tokenStorage, EntityManager $em, AccountManager $accountManager, $baseHost) { 
     $this->tokenStorage = $tokenStorage; 
     $this->em = $em; 
     $this->accountManager = $accountManager; 
     $this->baseHost = $baseHost; 
    } 

    public function onKernelRequest(GetResponseEvent $event) { 
     $request = $event->getRequest(); 

     $accountManager = $this->accountManager; 
     $accountManager->setCurrentAccount($this->getCurrentAccount($request)); 
    } 

    private function getCurrentAccount($request){ 
     if($this->getCurrentAccountByLoggedUser()) { 
      return $this->getCurrentAccountByLoggedUser(); 
     } 
     if($this->getCurrentAccountBySubDomain($request)) { 
      return $this->getCurrentAccountBySubDomain($request); 
     } 
     return; 
    } 

    private function getCurrentAccountBySubDomain($request) { 
     $host = $request->getHost(); 
     $baseHost = $this->baseHost; 

     $subdomain = str_replace('.'.$baseHost, '', $host); 

     $account = $this->em->getRepository('AppBundle:Account') 
       ->findOneBy([ 'urlName' => $subdomain ]); 

     if(!$account) return; 

     return $account; 
    } 

    private function getCurrentAccountByLoggedUser() { 
     if(is_null($token = $this->tokenStorage->getToken())) return; 

     $user = $token->getUser(); 
     return ($user instanceof User) ? $user->getAccount() : null; 
    } 

} 

services.yml

app.eventlistener.current_account_listener: 
    class: AppBundle\EventListener\CurrentAccountListener 
    arguments: 
     - "@security.token_storage" 
     - "@doctrine.orm.default_entity_manager" 
     - "@app.manager.account_manager" 
     - "%base_host%" 
    tags: 
     - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest } 

Và rất đơn giản quản lý tài khoản với setter và chỉ getter. Nếu tôi cần quyền truy cập vào tài khoản hiện tại, tôi gọi số

$this->get('app.manager.account_manager')->getCurrentAccount(); 

Mọi thứ đều hoạt động tốt.

Bây giờ tôi đang cố gắng thiết lập một số thông số từ dịch vụ của tôi với trình biên dịch qua

namespace AppBundle\DependencyInjection\Compiler; 

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; 
use Symfony\Component\DependencyInjection\ContainerBuilder; 

class ParametersCompilerPass implements CompilerPassInterface { 

    const ACCOUNT_MANAGER_SERVICE_ID = 'app.manager.account_manager'; 

    public function process(ContainerBuilder $container) { 

     if(!$container->has(self::ACCOUNT_MANAGER_SERVICE_ID)) { 
      return; 
     } 

     $currentAccount = $container->get(self::ACCOUNT_MANAGER_SERVICE_ID) 
      ->getCurrentAccount(); 

     $container->setParameter(
      'current_account', $currentAccount 
     ); 
    } 

} 

AppBundle.php

namespace AppBundle; 

    use AppBundle\DependencyInjection\Compiler\ParametersCompilerPass; 
    use Symfony\Component\DependencyInjection\Compiler\PassConfig; 
    use Symfony\Component\DependencyInjection\ContainerBuilder; 
    use Symfony\Component\HttpKernel\Bundle\Bundle; 

    class AppBundle extends Bundle 
    { 
     public function build(ContainerBuilder $container) 
     { 
      parent::build($container); 

      $container->addCompilerPass(new ParametersCompilerPass(), PassConfig::TYPE_AFTER_REMOVING); 
     } 
} 

tôi đã current_account như rỗng mọi thời gian, không có vấn đề gì PassConfig tôi sử dụng . Ý tưởng nào?

Cảm ơn sự quan tâm của bạn.

Trả lời

1

Mật khẩu biên dịch được thực hiện khi bạn chạy Symfony lần đầu tiên (lệnh CLI hoặc yêu cầu http đầu tiên). Khi cache được xây dựng (được biên dịch), mã này sẽ không bao giờ được thực thi nữa.

Giải pháp với các thông số [Tôi không khuyên này]

Nếu tham số của bạn có thể thay đổi từ một đến khác Yêu cầu HTTP bạn không nên sử dụng một tham số như một số dịch vụ có thể được khởi tạo trước khi tham số bạn đã sẵn sàng và những người khác sau. Mặc dù nếu đây là cách bạn muốn đi, bạn có thể thêm một sự kiện lắng nghe yêu cầu hạt nhân và sửa đổi/đặt tham số ở đó. Có một cái nhìn tại https://symfony.com/doc/current/components/http_kernel.html#component-http-kernel-event-table

tài khoản vãng lai trong user/phiên

Nếu currentAccount phụ thuộc vào người dùng đăng nhập, tại sao bạn không lưu trữ những thông tin ở người dùng hoặc phiên và truy cập vào nó từ các dịch vụ của bạn?

Các vấn đề liên quan