2017-05-15 57 views
2

開發一個Symfony 3應用程序,我需要根據URL來建立一個多網站。 這是我的parameters.yml文件:如何根據URL注入特定的參數?

... 
dbname_cda: my-website-cda 
dbname_pts: my-website-pts 
dbname_vis: my-website-vis 
... 

和這裏的config.yml

doctrine: 
    dbal: 
     default_connection: my-website 
     connections: 
      my-website: 
       driver: pdo_mysql 
       host:  "%dbhost%" 
       port:  "%dbport%" 
       dbname: "%_______%" 
       user:  "%dbuser%" 
       password: "%dbpassword%" 
       charset: UTF8 

https://my-website.com/cda將注入帕拉姆dbname_cda

https://my-website.com/pts將注入參數dbname_pts

https://my-website.com/vis將注入參數dbname_vis

實際上,除了根據URL從不同的數據庫加載數據之外,它是相同的網站。

謝謝你的幫助。

+0

使用子域名可以更容易地實現:'cda.my-website.com',因爲您可以在每個虛擬主機中使dbname var特定。 – COil

+0

感謝您的評論。實際上,我不允許在公司內創建子域..:/這就是爲什麼我想找到一個解決方法 –

+1

Symfony通過將所有配置文件(包括您的參數)「編譯」爲幾個大型緩存類來工作。您無法在請求的基礎上注入參數。只是不行。恐怕您需要深入瞭解整個服務/配置系統。本質上你需要創建一個請求監聽器,它實際上創建了一個教條連接並根據需要找出如何使用它。有點先進。做一些搜索多租戶系統的更多細節。 – Cerad

回答

1

考慮到您無法動態注入變量,因爲這些配置變量是在Symfony的「編譯時」定義的,所以下面是一個解決問題的方法。

聲明首先你在app/config/config.yml連接(我只把你cdapts連接):

doctrine: 
    dbal: 
     default_connection: cda 
     connections: 
      cda: 
       driver: pdo_mysql 
       host: '%database_host%' 
       port: '%database_port%' 
       dbname: '%database_cda_name%' 
       user: '%database_user%' 
       password: '%database_password%' 
       charset: UTF8 
      pts: 
       driver: pdo_mysql 
       host: '%database_host%' 
       port: '%database_port%' 
       dbname: '%database_pts_name%' 
       user: '%database_user%' 
       password: '%database_password%' 
       charset: UTF8 

    orm: 
     auto_generate_proxy_classes: '%kernel.debug%' 
     default_entity_manager: cda 
     entity_managers: 
      cda: 
       naming_strategy: doctrine.orm.naming_strategy.underscore 
       connection: cda 
       mappings: 
        AppBundle: ~ 
      pts: 
       naming_strategy: doctrine.orm.naming_strategy.underscore 
       connection: pts 
       mappings: 
        AppBundle: ~ 

然後,在app/config/services.yml聲明自己的doctrine服務的版本。該版本將取代Symfony定義的版本。

services: 
    # ... 

    doctrine_url_switcher: 
     class: AppBundle\Doctrine\Registry 
     decorates: doctrine 
     arguments: 
      - '@doctrine_url_switcher.inner' # Original Doctrine service 
      - '@request_stack' 
     public: false 

我使用這裏的service decoration機制的Symfony的定義doctrine服務的新版本。

現在,定義AppBundle\Doctrine\Registry類,擴展的Symfony的之一,將利用RequestStack的請求的默認實體管理器或連接時:

<?php 

namespace AppBundle\Doctrine; 

use Doctrine\Bundle\DoctrineBundle\Registry as BaseRegistry; 
use Symfony\Component\HttpFoundation\RequestStack; 

class Registry extends BaseRegistry 
{ 
    private $requestStack; 

    public function __construct(BaseRegistry $baseRegistry, RequestStack $requestStack) 
    { 
     parent::__construct(
      $baseRegistry->container, 
      $baseRegistry->getConnectionNames(), 
      $baseRegistry->getManagerNames(), 
      $baseRegistry->getDefaultConnectionName(), 
      $baseRegistry->getDefaultManagerName() 
     ); 

     $this->requestStack = $requestStack; 
    } 

    /** 
    * {@inheritdoc} 
    */ 
    public function getConnection($name = null) 
    { 
     $connection = null; 
     $request = $this->requestStack->getCurrentRequest(); 

     if ($request) { 
      $path = $request->getPathInfo(); 

      if (preg_match(':^/cda:', $path)) { 
       $connection = 'cda'; 
      } elseif (preg_match(':^/pts:', $path)) { 
       $connection = 'pts'; 
      } 
     } 

     return parent::getConnection($connection); 
    } 

    /** 
    * {@inheritdoc} 
    */ 
    public function getManager($name = null) 
    { 
     $manager = null; 
     $request = $this->requestStack->getCurrentRequest(); 

     if ($request) { 
      $path = $request->getPathInfo(); 

      if (preg_match(':^/cda:', $path)) { 
       $manager = 'cda'; 
      } elseif (preg_match(':^/pts:', $path)) { 
       $manager = 'pts'; 
      } 
     } 

     return parent::getManager($manager); 
    } 
} 

通過重寫Registry類的方法,我們利用的請求對象來確定哪個實體管理器或哪個連接應該被使用。使用特定的實體管理器名稱或連接名稱調用父方法,具體取決於URL。如果URL無法找到要使用的URL,則使用缺省值(在config.yml中定義)。

+0

謝謝。聽起來不錯 !我會嘗試讓你知道 –

+0

我自己測試過它,它工作:)我的第一個解決方案是使用服務工廠來配置doctrine服務,這是一個稍微優雅的解決方案,但有一些警告,因爲RequestStack是沒有系統地初始化。因此我喜歡這個解決方案。 –

+0

這似乎是我的解決方案爲你工作!這太棒了:) –