我想在我的项目中使用doctrine ODM,我想为每个客户创建一个单独的数据库。我希望能够通过我的API在运行时管理客户端。我现在的问题是:
当我设置doctrine ODM时,我必须在我的parameters.yml中设置我的数据库设置,但我希望能够在运行时选择数据库。我将有一个主数据库,包含我的所有fixture集合和客户端索引,以了解要选择哪个数据库,但客户端特定的东西将在那些客户端数据库中。每个Document类仍将链接到正常情况下的集合,但随后链接到不同的数据库。
有没有办法在运行时为Document类选择数据库?
所以我想去www.myproject.com/client1/item/list 我将列出dbclient1.Items集合中的每个项目,如果我访问www.myproject.com/client2/item/list,我将列出dbclient2.Items集合中的所有项目。
我希望我明确表达了我想要达到的目标......我找不到任何相关内容,但我认为如果我是第一个对此有疑问的人会很奇怪......在我之前有同样想法的人吗?
答案 0 :(得分:0)
有没有办法在运行时为Document类选择数据库?
是的,每次需要更改数据库时都可以调用$dm->getConfiguration()->setDefaultDb('some_db_name')
,但这可能会导致写入时发生意外行为。
根据我的经验(以及几年多租户应用程序的实践),最安全的方法是为每个上下文创建DocumentManager
的单独实例。你可以通过一个DocumentManager
正常配置你的参数但从不直接使用来实现这一点 - 而你需要有一个类来管理它的实例,fe:
use Doctrine\ODM\MongoDB\DocumentManager;
class DocumentManagerFactory
{
/**
* DocumentManager created by Symfony.
*
* @var DocumentManager
*/
private $defaultDocumentManager;
/**
* All DocumentManagers created by Factory so far.
*
* @var DocumentManager[]
*/
private $instances = array();
public function __construct(DocumentManager $dm)
{
$this->defaultDocumentManager = $dm;
}
public function createFor(Context $ctx)
{
$databaseName = $ctx->getDatabaseName();
if (isset($this->instances[$databaseName])) {
return $this->instances[$databaseName];
}
$configuration = clone $this->defaultDocumentManager->getConfiguration();
$configuration->setDefaultDB($databaseName);
return $this->instances[$databaseName] = DocumentManager::create(
$this->defaultDocumentManager->getConnection(),
$configuration,
$this->defaultDocumentManager->getEventManager()
);
}
}
由于这种方法,来自少数数据库的文档永远不会由一个DocumentManager
管理,您有一个类负责干预ODM配置并保留框架方法(事件订阅者等对每个{{1 }})。
答案 1 :(得分:0)
我还需要根据域名默认数据库名称(即seballot.mysite.com将使用seballot数据库)
我做了这个hack,虽然不是很好,但是效果很好。我在DocumentManager构造中添加了这些行
$dbName = isset($_SERVER["HTTP_HOST"]) ? explode('.', $_SERVER["HTTP_HOST"])[0] : 'default_database_of_my_root_website';
$this->config->setDefaultDB($dbName);