【问题标题】:Doctrine ODM Select database at runtimeDoctrine ODM 在运行时选择数据库
【发布时间】:2017-06-22 18:18:31
【问题描述】:

我想在我的项目中使用原则 ODM,并且我的想法是为我的每个客户建立一个单独的数据库。我希望能够通过我的 API 在运行时管理客户端。我现在的问题是:

当我设置原则 ODM 时,我必须在我的 parameters.yml 中设置我的数据库设置,但我希望能够在运行时选择数据库。我将拥有一个包含所有夹具集合和客户端索引的主数据库,以了解要选择哪个数据库,但客户端特定的东西将在这些客户端数据库中。每个 Document 类仍将链接到一个集合,就像在正常情况下一样,但是在不同的数据库中。

有没有办法在运行时为 Document 类选择数据库?

假设我去 www.myproject.com/client1/item/list 我将列出 dbclient1.Items 集合中的所有项目,如果我访问 www.myproject.com/client2/item/list,我将列出 dbclient2.Items 集合中的所有项目。

我希望我在这里明确了我想要达到的目标...我找不到任何关于此的信息,但我认为如果我是第一个对此提出问题的人会很奇怪...必须在我之前的人有同样的想法吗?

【问题讨论】:

    标签: php symfony configuration doctrine odm


    【解决方案1】:

    我还需要根据域名默认数据库名称(即 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);
    

    【讨论】:

      【解决方案2】:

      有没有办法在运行时为 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 配置和保留框架方法的类(每个 DocumentManager 的事件订阅者等都是相同的)。

      【讨论】:

      • 谢谢!我一直在为“写入起作用时的意外行为”而苦苦挣扎。我需要更改您的代码,可能是因为我的学说 conf,DocumentManager::create 的结果始终具有与默认 DocumentManagaer 相同的 databaseName。
      • 所以我改成了$configuration = clone $this->defaultDocumentManager->getConfiguration(); $newDm = DocumentManager::create( $this->defaultDocumentManager->getConnection(), $configuration, $this->defaultDocumentManager->getEventManager() ); $newDm->getConfiguration()->setDefaultDB($databaseName); return $this->instances[$databaseName] = $newDm;
      猜你喜欢
      • 2014-05-23
      • 1970-01-01
      • 1970-01-01
      • 2013-06-24
      • 2015-04-10
      • 1970-01-01
      • 2012-01-25
      • 2014-01-15
      • 1970-01-01
      相关资源
      最近更新 更多