Я хотел бы изменить имя схемы / имя базы данных во время выполнения, как это возможно, с именем таблицы , но класс ClassMetadataInfo
не отображает интерфейс для получения / установки этого свойства.
Я могу обойтись с изменением имен таблиц во время выполнения, если это абсолютно необходимо, но это не идеальное решение из-за количества таблиц, которые мы должны были бы хранить в одной схеме / БД.
Есть ли способ достичь того, что я хотел бы сделать? Заранее спасибо.
Примечание. Мне нужно предоставить полное имя таблицы с использованием заполнителя схемы в моем сопоставлении сущности на основе аннотаций (например, __schema_placeholder__.table_name
, для кросс-баз данных). Во время выполнения я хотел бы динамически переназначить сущность из __schema_placeholder__.table_name
=> real_schema_name.table_name
.
Вы можете динамически корректировать имена таблиц (и сопоставлений), подключаясь к системе событий doctrine с помощью прослушивателей / подписчиков.
т.е. «loadClassMetadata» является одним из событий доктрины, вы можете создать слушателя / подписчика, как описано в статье поваренной книги « Как регистрировать слушателей и подписчиков» .
config.yml
services: mapping.listener: class: Acme\YourBundle\EventListener\MappingListener tags: - { name: doctrine.event_listener, event: loadClassMetadata }
MappingListener
use Doctrine\ORM\Event\LoadClassMetadataEventArgs; class MappingListener { public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs) { $classMetadata = $eventArgs->getClassMetadata(); $table = $classMetadata->table; $oldName = $table['name']; // ... or $classMetaData->getTableName() // your logic here ... $table['name'] = 'new_table_name'; $classMetadata->setPrimaryTable($table); // ... or add a field-mapping like this $fieldMapping = array( 'fieldName' => 'about', 'type' => 'string', 'length' => 255 ); $classMetadata->mapField($fieldMapping);
ClassMetadata расширяет ClassMetadataInfo и предоставляет общедоступную переменную « table » (содержащую информацию о сопоставлении, предоставленную вашими аннотациями или yml), которые вы можете изменить!
Открытая переменная таблицы представляет собой массив со следующими элементами:
Вы можете динамически регистрировать слушателей / подписчиков на контроллере перед сохранением / обновлением.
$mappingListener = new MappingListener(); // ... maybe even modify the listener using reflection $evm = $this->get('doctrine')->getManager()->->getEventManager(); $evm->addEventListener('loadClassMetadata', $mappingListener);
Кроме того, вы можете ввести несколько соединений / имен базы данных и получить к ним доступ в своем приложении.
приложение / Config / config.yml
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 customer: driver: "%database_driver2%" host: "%database_host2%" port: "%database_port2%" dbname: "%database_name2%" user: "%database_user2%" password: "%database_password2%" charset: UTF8
Затем создайте разные сущностные менеджеры, используя …
$em = $this->get('doctrine')->getManager('default'); $em2 = $this->get('doctrine')->getManager('customer');
или хранилища
$customers = $this->get('doctrine') ->getRepository('AcmeCustomerBundle:Customer', 'customer') ->findAll() ;
… или динамически добавлять подключения
$this->get('doctrine') ->connection('mysql://username:password@localhost/test', 'dynamic_connection');
Подробнее о теме в главе поваренной книги. Как работать с несколькими менеджерами и подключениями .
Ответ @ nifr – это путь. Я думаю, что нужно отметить, что вам нужно очистить кеш доктрины, чтобы вызвать loadClassMetaData!
$ app/console doctrine:cache:clear-metadata --env=test