我使用静态数据库处理登录和租户信息,使用第二个数据库来保存用户数据。
app/config/config.yml:
doctrine:
dbal:
default_connection: default
connections:
default:
driver: "%database_driver%"
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
tenantdb:
driver: "%database_driver%"
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
orm:
default_entity_manager: default
entity_managers:
default:
connection: default
mappings:
MyCoreBundle: ~
tenantdb:
connection: tenantdb
mappings:
MyAppBundle: ~
然后,在控制器中,不要再使用
$something = $this->getDoctrine()
->getManager()
->getRepository('MyAppBundle:Thing')
->findAll();
我们做了:
$something = $this->getDoctrine()
->getManager('tenantdb')
->getRepository('MyAppBundle:Thing', 'tenantdb')
->findAll();
您可以在此处找到详细信息:
http://symfony.com/doc/current/cookbook/doctrine/multiple_entity_managers.html
然后,基于 Symfony2,动态DB连接/早期重写Doctrine服务,
我设置了一个服务来根据请求的子域名(例如tenant1.example.com tenant2.example.com)切换数据库。
src/MyCoreBundle/Resources/config/services.yml:
services:
my.database_switcher:
class: MyCoreBundle\EventListener\DatabaseSwitcherEventListener
arguments: [@request, @doctrine.dbal.tenantdb_connection]
scope: request
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
MyCoreBundle\EventListener\DatabaseSwitcherEventListener.php
namespace MyCoreBundle\EventListener;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\DBAL\Connection;
class DatabaseSwitcherEventListener {
private $request;
private $connection;
public function __construct(Request $request, Connection $connection) {
$this->request = $request;
$this->connection = $connection;
}
public function onKernelRequest() {
$connection = $this->connection;
if (! $connection->isConnected()) {
$params = $this->connection->getParams();
$subdomain = __GET_SUBDOMAIN__();
$oldname = preg_replace (
"/_tenant_$subdomain|_template/",
'',
$params['dbname']
);
$params['dbname'] = $oldname . ($subdomain ? "_tenant_$subdomain"
: "_template");
$connection->__construct(
$params,
$connection->getDriver(),
$connection->getConfiguration(),
$connection->getEventManager()
);
$connection->connect();
}
}
}
为了方便起见,我们有一个名为XXX_template的“额外”租户数据库,系统管理员在进行全局更改时连接到该数据库。
计划是在创建租户时将此数据库复制到租户数据库。