symfony2 프로젝트에는 기본 데이터베이스와 많은 하위 데이터베이스가 있습니다. 각 하위 데이터베이스는 각 사용자에 대해 작성되고 데이터베이스 신임은 기본 데이터베이스에 저장됩니다. 사용자가 로그인하면 사용자 별 데이터베이스 자격 증명이 기본 데이터베이스에서 가져오고 이상 적으로 하위 데이터베이스 연결이 설정되어야합니다. 나도 같은 위해 인터넷 검색, 나는 다수의 솔루션을 건너 와서 마지막으로 다음과 같은 한 : 동적 데이터베이스 연결 symfony2
#config.yml
doctrine:
dbal:
default_connection: default
connections:
default:
dbname: maindb
user: root
password: null
host: localhost
dynamic_conn:
dbname: ~
user: ~
password: ~
host: localhost
orm:
default_entity_manager: default
entity_managers:
default:
connection: default
auto_mapping: true
dynamic_em:
connection: dynamic_conn
auto_mapping: true
내가 주 데이터베이스와 자식 데이터베이스에 대한 빈 연결에 연결하는 기본 연결을 생성, 유사 I을 생성 된 엔티티 관리자. 은 그 때 나는 기본 이벤트 리스너를 생성하고 'onKernelRequest'에 다음 코드를 추가 :
public function onKernelRequest(GetResponseEvent $event) //works like preDispatch in Zend
{
//code to get db credentials from master database and stored in varaiables
....
$connection = $this->container->get(sprintf('doctrine.dbal.%s_connection', 'dynamic_conn'));
$connection->close();
$refConn = new \ReflectionObject($connection);
$refParams = $refConn->getProperty('_params');
$refParams->setAccessible('public'); //we have to change it for a moment
$params = $refParams->getValue($connection);
$params['dbname'] = $dbName;
$params['user'] = $dbUser;
$params['password'] = $dbPass;
$refParams->setAccessible('private');
$refParams->setValue($connection, $params);
$this->container->get('doctrine')->resetEntityManager('dynamic_em');
....
}
위의 코드는 자식 데이터베이스 매개 변수를 설정하고 dynamic_em 엔티티 관리자를 재설정합니다.
일부 컨트롤러에서 다음 작업을 수행하면 하위 데이터베이스에서 데이터를 가져 와서 제대로 작동합니다.
$getblog= $em->getRepository('BloggerBlogBundle:Blog')->findById($id); //uses doctrine
그러나 다음 코드에서 볼 수있는 보안 컨텍스트를 사용할 때 '아니오 데이터베이스 선택'오류가 발생합니다.
$securityContext = $this->container->get('security.context');
$loggedinUserid = $securityContext->getToken()->getUser()->getId();
어떻게 데이터베이스 연결을 동적으로 설정하고 보안 컨텍스트를 사용할 수 있습니까?
업데이트 : -
시행 착오, 그리고 주위에 인터넷 검색에 소요되는 많은 시간 후, 나는 security.context
이 onKernelRequest
의 실행 전에 설정되어 있는지 깨달았다. 이제 질문은 은 security.context에 데이터베이스 연결 세부 정보를 주입하는 방법이며 은을 주입하려면?
DBAL 및 보안 컨텍스트가 설정되고 보안 토큰이 만들어지는 지점에 도달해야하며 데이터베이스 연결 세부 정보를 조작 할 수 있습니다.
다음 링크에있는 사람이 언급했듯이, 나는 내가하고 싶은 일을 정확하게 변경했다. 나에게 다음 코드를 잎 http://forum.symfony-project.org/viewtopic.php?t=37398&p=124413
내 프로젝트에 추가 :
컴파일러 패스로 만들어집니다#config.yml //remains unchanged, similar to above code
은 다음과 같습니다
// src/Blogger/BlogBundle/BloggerBlogBundle.php
namespace Blogger\BlogBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Blogger\BlogBundle\DependencyInjection\Compiler\CustomCompilerPass;
class BloggerBlogBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new CustomCompilerPass());
}
}
컴파일러 패스는 다음과 같다 :
# src/Blogger/BlogBundle/DependencyInjection/Compiler/CustomCompilerPass.php
class CustomCompilerPassimplements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$connection_service = 'doctrine.dbal.dynamic_conn_connection';
if ($container->hasDefinition($connection_service))
{
$def = $container->getDefinition($connection_service);
$args = $def->getArguments();
$args[0]['driverClass'] = 'Blogger\BlogBundle\UserDependentMySqlDriver';
$args[0]['driverOptions'][] = array(new Reference('security.context'));
$def->replaceArgument(0, $args[0]);
}
}
}
드라이버 클래스 코드는 다음과 같습니다.
# src/Blogger/BlogBundle/UserDependentMySqlDriver.php
use Doctrine\DBAL\Driver\PDOMySql\Driver;
class UserDependentMySqlDriver extends Driver
{
public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
{
$dbname = ..... //store database name in variable
$params['dbname'] = $dbname;
return parent::connect($params, $username, $password, array());
}
}
위의 코드가 내 프로젝트에 추가되었으며이 문제가 내 실제 문제라고 생각합니다.
하지만 지금은 다음과 같은 오류 얻을 :
ServiceCircularReferenceException: Circular reference detected for service "security.context", path: "profiler_listener -> profiler -> security.context -> security.authentication.manager -> fos_user.user_provider.username_email -> fos_user.user_manager -> doctrine.orm.dynamic_manager_entity_manager -> doctrine.dbal.dynamic_conn_connection".
방법, 내 코드가 작동 얻을 수 있습니까? 나는 내가 여기서 잘못된 것을하고 있다고 확신하고 어떤 힌트와 도움을 주셔서 감사합니다.
는'security.context'를 사용하여 코드는 *은'onKernelRequest' 이벤트 전에 * 실행입니까? security.context의 일부 종속성은 'dynamic_em'을 사용해야합니다. – arnaud576875
security.context 코드는 getRespository 코드가 추가 된 것과 동일한 작업에 추가됩니다. 따라서 onKernelRequest는 security.context보다 먼저 실행됩니다. –
@ 존 Sf 2.3.2로 테스트 한 결과 첫 번째 솔루션이 저에게 효과적이었습니다. 이벤트 구독자를 사용하여 연결 개체를 수정했습니다. 컨트롤러는 나중에 "슬레이브"데이터베이스에서 행을 가져 와서 현재 로그인 한 사용자 ('FOSUserBundle' 사용)를로드합니다. 보안 컨텍스트는 이벤트 디스패치 단계에서 채워지며 처음에는 단순히 청취자 우선 순위를 변경하는 문제라고 생각했습니다. 만약 당신이 이미 그것을 알아 내지 못했다면 아마도 Symfony 버전을 사용하고 계신지 말할 수있을 것입니다. – gilden