Можно ли использовать два разных менеджера документов с разными базами данных для одного пакета в Symfony?

1

Моя цель состоит в том, чтобы два разных менеджера документов подключались к различным базам данных, которые используют одни и те же модели баз данных.

Я сильно изменил мою модель базы данных, и я хотел бы написать специальный сценарий миграции, который извлекает объекты из старой модели, считывает его значения, а затем создает новый объект в новой схеме с информацией о старом объекте.

Я нашел связанный с этим вопрос stackoverflow: Работа с двумя менеджерами сущностей в том же пакете в Symfony2

Тем не менее, это решение предлагает использовать разные префиксы для каждой базы данных и хранит классы для модели данных в разных папках:

doctrine:
dbal:
    default_connection:   default
    connections:
        default:
            driver:   %database_driver%
            host:     %database_host%
            port:     %database_port%
            dbname:   %database_name%
            user:     %database_user%
            password: %database_password%
            charset:  UTF8
        second:
            driver:   %database_sqlite_driver%
            host:     ~
            port:     ~
            dbname:   %database_sqlite_shop_name%
            path:     %database_sqlite_shop_name%
            user:     ~
            password: ~
            charset:  UTF8

orm:
    auto_generate_proxy_classes: %kernel.debug%
    default_entity_manager:   default
    entity_managers:
        default:
            connection:       default
            mappings:
                YourBundle:
                  # you must specify the type
                  type:     "annotation"    
                  # The directory for entity (relative to bundle path)
                  dir:      "Entity/FirstDb"        
                  #the prefix 
                  prefix:   "Your\Bundle\Entity\FirstDb" 
        shop:
            connection:       second
            mappings:
                YourBundle:
                  type: "annotation"
                  #here the second path where entity for the connection stand
                  dir: "Entity/SecondDb" 
                  #the prefix
                  prefix: "Your\Bundle\Entity\SecondDb" 

Мне бы очень хотелось иметь два разных объекта менеджера документов, которые используют одни и те же модели в одной папке, но подключены к различным базам данных. Это возможно?

Показать ещё 1 комментарий
Теги:
doctrine2
doctrine-odm
doctrine-mongodb

1 ответ

0
Лучший ответ

Я узнал, что действительно можно подключиться к различным базам данных в том же пакете Symfony Bundle. Этот ответ привел меня к возможному решению: qaru.site/questions/351395/...

#services.yml
acme_app.dynamic_connection:
class: %acme.dynamic_doctrine_connection.class%
calls:
    - [setDoctrineConnection, @doctrine.dbal.default_connection]]


<?php

namespace Acme\Bundle\AppBundle;

use Doctrine\DBAL\Connection;
use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
use Exception;

class DynamicDoctrineConnection
{
    /**
     * @var Connection
     */
    private $connection;

    /**
     * Sets the DB Name prefix to use when selecting the database to connect to
     *
     * @param  Connection       $connection
     * @return SiteDbConnection $this
     */
    public function setDoctrineConnection(Connection $connection)
    {
        $this->connection = $connection;

        return $this;
    }

    public function setUpAppConnection()
    {
        if ($this->request->attributes->has('appId')) {
            $connection = $this->connection;
            $params     = $this->connection->getParams();

            // we also check if the current connection needs to be closed based on various things
            // have left that part in for information here
            // $appId changed from that in the connection?
            // if ($connection->isConnected()) {
            //     $connection->close();
            // }

            // Set default DB connection using appId
            //$params['host']   = $someHost;
            $params['dbname'] = 'Acme_App'.$this->request->attributes->get('appId');

            // Set up the parameters for the parent
            $connection->__construct(
                $params, $connection->getDriver(), $connection->getConfiguration(),
                $connection->getEventManager()
            );

            try {
                $connection->connect();
            } catch (Exception $e) {
                // log and handle exception
            }
        }

        return $this;
    }
}

С помощью вышеприведенного решения можно написать службу, которая может быть вызвана для изменения базы данных, к которой подключен текущий диспетчер сущностей к другой базе данных.

К сожалению, решение выше работает только для драйвера PDO (Mysql). Поскольку наш стек технологий включает в себя mongodb, и мы используем пакет doctrine-mongodb, мне пришлось искать другое решение.

Документация doctrine-mongodb содержит раздел о создании настраиваемого менеджера документов здесь: http://docs.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/reference/introduction.html

Мне не удалось получить правильные сопоставления документов doctrine-mongodb odm для работы с инструкциями в документе, и поэтому единственным решением для меня было создать простую связь с PHP-монголементом:

$mongo = new \Mongo('mongodb://localhost:27017');
$legacyDbDocumentMangager = $mongo->selectDB('backed_up_prod_db');
$legacyUserCollection = $legacyDbDocumentMangager->selectCollection('User');
$user = $legacyUserCollection->findOne(array('email' => '[email protected]'));

Единственным отличием между этим простым драйвером php mongodb и догмой doctrine-mongodb является то, что результаты запросов этого драйвера являются ассоциативными массивами, а результаты доктрины-mongodb odm diver - это объекты.

Надеюсь, эта информация кому-то полезна.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню