Ответ 1
Как вы можете видеть, FOSUserBundle может иметь только один EntityManager. Вы можете увидеть это из настроек orm.xml
<service id="fos_user.entity_manager" factory-service="doctrine" factory-method="getManager" class="Doctrine\ORM\EntityManager" public="false">
<argument>%fos_user.model_manager_name%</argument>
</service>
Параметр% fos_user.model_manager_name%, указанный в параметрах как model_manager_name
fos_user:
db_driver: ~ # Required
user_class: ~ # Required
firewall_name: ~ # Required
model_manager_name: ~
Итак, в конструктор приходит экземпляр EntityManager, который не принимает второй параметр в getRepository. Поэтому стандартный FOSUserBundle может работать только с одной базой данных.
Но это еще не конец истории, это Symfony:) Мы можем написать UserManager, который может использовать разные подключения к db. В настройке см. Fos_user.user_manager - файл fos_user.user_manager.default. Мы находим его в orm.xml
<service id="fos_user.user_manager.default" class="FOS\UserBundle\Doctrine\UserManager" public="false">
<argument type="service" id="security.encoder_factory" />
<argument type="service" id="fos_user.util.username_canonicalizer" />
<argument type="service" id="fos_user.util.email_canonicalizer" />
<argument type="service" id="fos_user.entity_manager" />
<argument>%fos_user.model.user.class%</argument>
</service>
Мы можем переопределить этот класс, чтобы добавить дополнительный параметр, который определит, какое соединение вы хотите использовать. Далее ManagerFactory вы можете получить желаемый ObjectManager. Я написал простой пример для двух таблиц данных (если вам нужно больше баз данных, вы можете написать factory для этой службы)
определить свои услуги в services.yml
services:
acme.user_manager.conn1:
class: Acme\DemoBundle\Service\UserManager
public: true
arguments:
- @security.encoder_factory
- @fos_user.util.username_canonicalizer
- @fos_user.util.email_canonicalizer
- @doctrine
- 'conn1_manager'
- %fos_user.model.user.class%
acme.user_manager.conn2:
class: Acme\DemoBundle\Service\UserManager
public: true
arguments:
- @security.encoder_factory
- @fos_user.util.username_canonicalizer
- @fos_user.util.email_canonicalizer
- @doctrine
- 'conn2_manager'
- %fos_user.model.user.class%
Ваш менеджер
/**
* Constructor.
*
* @param EncoderFactoryInterface $encoderFactory
* @param CanonicalizerInterface $usernameCanonicalizer
* @param CanonicalizerInterface $emailCanonicalizer
* @param RegistryInterface $doctrine
* @param string $connName
* @param string $class
*/
public function __construct(EncoderFactoryInterface $encoderFactory, CanonicalizerInterface $usernameCanonicalizer,
CanonicalizerInterface $emailCanonicalizer, RegistryInterface $doctrine, $connName, $class)
{
$om = $doctrine->getEntityManager($connName);
parent::__construct($encoderFactory, $usernameCanonicalizer, $emailCanonicalizer, $om, $class);
}
/**
* Just for test
* @return EntityManager
*/
public function getOM()
{
return $this->objectManager;
}
и простой тест
/**
* phpunit -c app/ src/Acme/DemoBundle/Tests/FOSUser/FOSUserMultiConnection.php
*/
class FOSUserMultiConnection extends WebTestCase
{
public function test1()
{
$client = static::createClient();
/** @var $user_manager_conn1 UserManager */
$user_manager_conn1 = $client->getContainer()->get('acme.user_manager.conn1');
/** @var $user_manager_conn2 UserManager */
$user_manager_conn2 = $client->getContainer()->get('acme.user_manager.conn2');
/** @var $om1 EntityManager */
$om1 = $user_manager_conn1->getOM();
/** @var $om2 EntityManager */
$om2 = $user_manager_conn2->getOM();
$this->assertNotEquals($om1->getConnection()->getDatabase(), $om2->getConnection()->getDatabase());
}
}
Мне жаль, что ответ был таким большим. Если что-то неясно до конца, я помещаю код в github