私のsymfony2プロジェクトには、メインデータベースと多くの子データベースがあります。それぞれの子データベースは各ユーザーごとに作成され、データベースの資格情報はメインデータベースに格納されます。ユーザーがログインすると、ユーザー固有のデータベース資格情報がメイン・データベースからフェッチされ、子データベース接続が理想的に確立されます。 私は同じのためにGoogleで検索し、私は解決策の数accross来て、最終的には次のことをやった:動的データベース接続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
私は同様に、メインデータベースと子データベースの空の接続に接続するためのデフォルトの接続を作成しました作成されたエンティティマネージャ。 は、それから私は、デフォルトのイベントリスナーを作成し、「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
ただし、次のコードに示すようにセキュリティコンテキストを使用すると、「NO DATABASE SELECTED」というエラーが表示されます。
$securityContext = $this->container->get('security.context');
$loggedinUserid = $securityContext->getToken()->getUser()->getId();
データベース接続を動的に設定してセキュリティコンテキストを使用する方法を教えてください。
UPDATE: - 試行錯誤の上に費やした多くの時間の後
、そして周りのグーグル、私は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の前に実行されると仮定します。 –
@John私はSf 2.3.2でそれをテストしました。最初の解決策が私のために働いています。私はイベントサブスクライバを使用して接続オブジェクトを変更しました。コントローラは後で「スレーブ」データベースから行を取り出し、現在ログインしているユーザ(「FOSUserBundle」で使用)をロードします。セキュリティコンテキストは、イベントディスパッチフェーズ中に配置され、一見すると、単にリスナーの優先順位を変更する問題であると思っていました。もしあなたがそれをまだ分かっていないのであれば、あなたはSymfonyのどのバージョンを使っているのか分かりますか? – gilden