Доктрина 1.2 PHP ORM - полиморфные запросы с наследованием таблицы класса

Я экспериментирую с Доктриной ORM (v1.2) для PHP. Я определил класс "алкоголь" с двумя дочерними классами "джин" и "виски". Я использую конкретное наследование (наследование таблицы класса в большей части литературы) для отображения классов на три отдельных таблицы базы данных.

Я пытаюсь выполнить следующее:

$liquor_table = Doctrine_Core::getTable('liquor');
$liquors = $liquor_table->findAll();

Первоначально, я ожидал, что $liquors будет Doctrine_Collection, содержащим все спиртные напитки, ли они быть виски или джином. Но когда я выполняю код, я получаю пустой набор, несмотря на наличие нескольких строк в таблицах базы данных джина и виски. На основе сгенерированного SQL я понимаю почему: ORM запрашивает таблицу "алкоголя" а не таблицы виски/джина, где фактические данные хранятся.

Обратите внимание, что код работает отлично, когда я переключаю тип наследования на агрегирование столбца (простое наследование таблицы).

Что лучший способ состоит в том, чтобы получить Doctrine_Collection, содержащий все спиртные напитки?

Обновление

Еще после некоторого исследования похоже, что я ожидаю, что Доктрина выполнит SQL UNION операция негласно для объединения наборов результатов от таблиц "виски" и "джина".

Это известно как полиморфный запрос.

Согласно этому билету, эта функциональность не доступна в Доктрине 1.x. Это предназначено для этих 2,0 выпусков. (также см. документы Доктрины 2.0 для CTI).

Таким образом в свете этой информации, каков был бы самый чистый, самый эффективный способ работать вокруг этого дефицита? Переключиться на единственное наследование таблицы? Выполнить два запроса DQL и вручную объединить получающийся Doctrine_Collections?

15
задан Josh Johnson 9 July 2010 в 02:19
поделиться

2 ответа

единственным стабильным и полезным режимом наследования Doctrine на данный момент является column_aggregation. Остальные я пробовал в разных проектах. С помощью column_aggregation можно имитировать полиморфные запросы. Наследование в целом - это то, что в Doctrine (1.x) немного глючит. В версии 2.x это изменится, так что в будущем у нас могут появиться лучшие возможности.

3
ответ дан 1 December 2019 в 05:26
поделиться

Я написал (не готово к производству) начало ORM, которое будет делать именно то, что вы ищете. пока вернулся. Просто чтобы у меня было доказательство концепции. Все мои исследования показали, что вы каким-то образом смешиваете код и данные (информацию о подклассе в таблице ликера).

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

Как вы будете распространять подробности, зависит только от вас. Я думаю, что наиболее нормализованный (и любой может поправить меня, если я ошибаюсь) способ сделать это - сохранить все поля, которые появляются в вашем классе спиртных напитков, в таблице напитков. Затем для каждого подкласса создайте таблицу, в которой хранятся конкретные данные, относящиеся к типу подкласса. Это момент, когда вы смешиваете код и данные, потому что ваш код читает таблицу ликвора, чтобы получить имя подкласса для выполнения соединения.

Я буду использовать автомобили и мотоциклы, а также некоторые минимальные, но тривиальные различия между ними для своего примера:

Ride
----
id
name
type

(1, 'Sebring', 'Car')
(2, 'My Bike', 'Bicycle')

Bicycle
-------
id
bike_chain_length

(2, '2 feet')

Car
---
id
engine_size

(1, '6 cylinders')

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

Надеюсь, это поможет!

0
ответ дан 1 December 2019 в 05:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: