Doctrine ODM在运行时选择数据库

时间:2017-02-05 20:44:26

标签: php symfony configuration doctrine odm

我想在我的项目中使用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集合中的所有项目。

我希望我明确表达了我想要达到的目标......我找不到任何相关内容,但我认为如果我是第一个对此有疑问的人会很奇怪......在我之前有同样想法的人吗?

2 个答案:

答案 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);