Moh*_*ria 40 symfony doctrine-orm fosuserbundle
如果相当容易,在Symfony中使用基于URL的不同实体管理器/连接.使用以下路由配置
connection:
pattern: /a/{connection}
defaults: { _controller: AcmeTestBundle:User:index }
Run Code Online (Sandbox Code Playgroud)
并从以下食谱;
我的控制器看起来像这样;
class UserController extends Controller
{
public function indexAction($connection)
{
$products = $this->get('doctrine')
->getRepository('AcmeStoreBundle:Product', $connection)
->findAll()
;
..................
Run Code Online (Sandbox Code Playgroud)
我将能够从不同的em/connection /数据库中获取产品信息.
现在,如果我在路由中添加这样的内容;
login:
pattern: /a/{connection}/login
defaults: { _controller: FOSUserBundle:Security:login }
Run Code Online (Sandbox Code Playgroud)
如何轻松地使登录使用连接变量中定义的连接?
此设置假设每个数据库都有自己的用户登录信息(fos_user表).
编辑:更新的路由信息
EDIT2:
我仍然是PHP/Symfony/Doctrine的新手,所以如果我在这里完全错了,请原谅我.我尝试在FOS\UserBundle\Doctrine\UserManager中手动设置连接.以下是该类的构造函数
//
use Doctrine\Common\Persistence\ObjectManager;
//
public function __construct(EncoderFactoryInterface $encoderFactory, CanonicalizerInterface $usernameCanonicalizer, CanonicalizerInterface $emailCanonicalizer, ObjectManager $om, $class)
{
parent::__construct($encoderFactory, $usernameCanonicalizer, $emailCanonicalizer);
$this->objectManager = $om;
$this->repository = $om->getRepository($class);
$metadata = $om->getClassMetadata($class);
$this->class = $metadata->getName();
}
Run Code Online (Sandbox Code Playgroud)
在控制器中,我们可以使用以下方法将em更改为"testing"
$em = $this->get('doctrine')->getManager('testing');
$repository = $this->get('doctrine')->getRepository($class, 'testing')
Run Code Online (Sandbox Code Playgroud)
为此,我将代码更改为以下代码以使用EntityManager而不是ObjectManager.
//
//use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\ORM\EntityManager;
//
public function __construct(EncoderFactoryInterface $encoderFactory, CanonicalizerInterface $usernameCanonicalizer, CanonicalizerInterface $emailCanonicalizer, EntityManager $om, $class)
{
parent::__construct($encoderFactory, $usernameCanonicalizer, $emailCanonicalizer);
$this->objectManager = $om;
$this->repository = $om->getRepository($class);
$metadata = $om->getClassMetadata($class);
$this->class = $metadata->getName();
}
Run Code Online (Sandbox Code Playgroud)
我的应用程序工作正常,没有错误.
从它与控制器的工作方式,我尝试通过向此行添加参数来更改连接,但它仍然使用默认连接.
$this->repository = $om->getRepository($class, 'testing');
Run Code Online (Sandbox Code Playgroud)
我还能在这里找到什么?
Ale*_* B. 12
如您所见,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>
Run Code Online (Sandbox Code Playgroud)
参数%fos_user.model_manager_name%在设置中指定为model_manager_name
fos_user:
db_driver: ~ # Required
user_class: ~ # Required
firewall_name: ~ # Required
model_manager_name: ~
Run Code Online (Sandbox Code Playgroud)
因此进入构造函数的是EntityManager的实例,它不接受getRepository中的第二个参数.因此,标准FOSUserBundle只能与一个数据库一起使用.
但这不是故事的结尾,它是Symfony :)我们可以写出UserManager,它可以使用不同的数据库连接.在该设置中,请参阅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>
Run Code Online (Sandbox Code Playgroud)
我们可以覆盖此类以添加一个额外的参数,该参数将确定您要使用的连接类型.通过ManagerFactory,您可以获得所需的ObjectManager.我为两个数据库编写了简单的示例(如果您需要更多数据库,可以为此服务编写工厂)
在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%
Run Code Online (Sandbox Code Playgroud)
你的经理
/**
* 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;
}
Run Code Online (Sandbox Code Playgroud)
和简单的测试
/**
* 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());
}
}
Run Code Online (Sandbox Code Playgroud)
对不起,答案太大了.如果到底有什么不清楚,我把代码放在github上
| 归档时间: |
|
| 查看次数: |
5611 次 |
| 最近记录: |