考慮到您無法動態注入變量,因爲這些配置變量是在Symfony的「編譯時」定義的,所以下面是一個解決問題的方法。
聲明首先你在app/config/config.yml
連接(我只把你cda
和pts
連接):
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
中定義)。
使用子域名可以更容易地實現:'cda.my-website.com',因爲您可以在每個虛擬主機中使dbname var特定。 – COil
感謝您的評論。實際上,我不允許在公司內創建子域..:/這就是爲什麼我想找到一個解決方法 –
Symfony通過將所有配置文件(包括您的參數)「編譯」爲幾個大型緩存類來工作。您無法在請求的基礎上注入參數。只是不行。恐怕您需要深入瞭解整個服務/配置系統。本質上你需要創建一個請求監聽器,它實際上創建了一個教條連接並根據需要找出如何使用它。有點先進。做一些搜索多租戶系統的更多細節。 – Cerad