Я хочу использовать доктрину ODM для своего проекта, и у меня была идея создать отдельную базу данных для каждого из моих клиентов. Я хочу иметь возможность управлять клиентами во время выполнения через мой API. Мой вопрос сейчас:
Когда я настраиваю доктрину ODM, мне нужно установить настройки базы данных в моем файле settings.yml, но я хочу иметь возможность выбирать базу данных во время выполнения. У меня будет одна основная база данных со всеми моими коллекциями приборов и клиентским индексом, чтобы знать, какую базу данных выбрать, но в этих клиентских базах данных будут специфические для клиента вещи. Каждый класс Document будет по-прежнему связан с коллекцией, как в обычной ситуации, но затем в другой базе данных.
Есть ли способ выбрать базу данных для класса документа во время выполнения?
Допустим, я иду на www.myproject.com/client1/item/list
Я перечислю каждый элемент в коллекции dbclient1.Items, и если я зайду на www.myproject.com/client2/item/list, я перечислю все элементы в коллекции dbclient2.Items.
Я надеюсь, что ясно дал понять, чего я хочу достичь здесь … Я ничего не мог найти по этому поводу, но я думаю, что было бы странно, если бы я был первым человеком, который задал вопрос об этом … Должно быть, были люди до меня с той же идеей не так ли?
Есть ли способ выбрать базу данных для класса документа во время выполнения?
Да, вы можете позвонить $dm->getConfiguration()->setDefaultDb('some_db_name')
каждый раз, когда вам нужно изменить базу данных, но это может привести к неожиданному поведению, когда запись вступает в игру.
Исходя из моего опыта (и нескольких лет практики в мультитенантных приложениях), самый пуленепробиваемый способ — это создавать отдельные экземпляры DocumentManager
за каждый контекст. Вы можете достичь этого, имея один DocumentManager
обычно настраивается с вашими параметрами, но никогда не используется напрямую — вместо этого вам нужен класс, который будет управлять его экземплярами, например:
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
).
Других решений пока нет …