Заказ по многим-многим отношениям с FuelPHP
У меня проблема с сортировкой по многим-многим отношениям. То, чего я пытаюсь достичь, похоже, должно быть довольно простым, но после того, как я сильно ударился головой о Топливо, я все еще не могу заставить его работать.
(Между прочим, я понимаю, более или менее этот вопрос был задан ранее, но так как (а) в то время было невозможно разобраться в ленивых отношениях, и (б) я получил гораздо больше подробно о точной проблеме, с которой я столкнулся, я подумал, что стоит задать отдельный вопрос...)
Вот проблема, которую я имею:
У меня есть модель "Предмет". У элементов могут быть дочерние элементы (которые также являются элементами), соединенные посредством отношения "многие ко многим" через таблицу "items_items" со столбцами "parent_id" и "child_id". В таблице "items_items" также есть столбец "sortorder", так что можно установить порядок дочерних элементов.
Создание отдельной модели для этого отношения показалось мне излишним, поэтому порядок обновляется наблюдателем, который обновляет сортировку дочерних элементов при сохранении родителя (с помощью метода "_event_after_save" в Model_Item). Кажется, это работает нормально.
Однако проблема, с которой я столкнулся, заключается в том, что я могу получить порядок сортировки, работающий либо с отложенной загрузкой, либо с активной загрузкой, но не с обоими. Независимо от того, какой из них работает, другой выдает ошибки Fuel, поэтому в настоящее время единственный способ заставить загружаться как с нетерпением, так и с отложенной загрузкой - это отказаться от предложения 'order_by' при загрузке с нетерпением. Вот три способа, которыми я пытался определить отношения "дети":
Подход № 1
- Этот подход должен работать на соответствующей странице в документации FuelPHP.
Нет ошибок при активной или отложенной загрузке, но в любом случае order_by не соблюдается (дочерние элементы упорядочены по id, а не по sortorder)
'children' => array( 'table_through' => 'items_items', 'key_through_from' => 'parent_id', 'key_through_to' => 'child_id', 'model_to' => 'Model_Item', 'order_by' => array( 'items_items.sortorder' => 'ASC' ), )
Подход № 2
- Работает как нужно с энергичной загрузкой
Вызывает ошибку топлива с отложенной загрузкой ("Столбец не найден: 1054 Неизвестный столбец" items_items.sortorder "в" предложении заказа "). Это происходит потому, что items_items имеет псевдоним" t0_through "в предложении JOIN, но не в ORDER BY пункт.
'children' => array( 'table_through' => 'items_items', 'key_through_from' => 'parent_id', 'key_through_to' => 'child_id', 'model_to' => 'Model_Item', 'conditions' => array( 'order_by' => array( 'items_items.sortorder' => 'ASC' ), ) )
Подход № 3
- Работает как нужно с ленивой загрузкой
Вызывает ошибку топлива с энергичной загрузкой (фактически, обратная версия № 2, выше)
'children' => array( 'table_through' => 'items_items', 'key_through_from' => 'parent_id', 'key_through_to' => 'child_id', 'model_to' => 'Model_Item', 'conditions' => array( 'order_by' => array( 't0_through.sortorder' => 'ASC' ), ) )
В немного отчаянном хаке я попытался объединить подходы 2 и 3, описанные выше, определив два отдельных отношения ('children' и 'child') - одно для быстрой загрузки, другое для отложенной загрузки, но это все еще ломает мое приложение, потому что оно делает процесс удаления выдает похожие ошибки. Я мог бы попытаться исправить это, но я чувствую, что это будет просто взломать взломать. Вместо этого я хотел бы получить надежный способ упорядочения дочерних элементов, который работает независимо от того, загружены они или загружены. Документы Топлива предполагают, что это должно быть выполнимо (подход № 1, выше), но я просто не могу заставить это работать...
Любая помощь будет очень высоко ценится!
2 ответа
Мне наконец удалось исправить эту проблему. Это оказалось проблемой с текущей версией ORM Fuel (версия 1.7).
Для меня сработало обновить ORM до более поздней версии разработки ( 60cc4eb576 в ветке ORM 1.8 / development), а затем установить 'order_by' для отношения "многие ко многим" следующим образом:
...
'conditions' => array(
'order_by' => array(
'items_items.sortorder' => 'ASC'
),
)
...
Это комбинация подходов 2 и 3, описанных выше, и не совсем синтаксис, предлагаемый в настоящее время в документации, но, похоже, работает как ожидалось / желательно как для быстрой, так и для ленивой загрузки.
С точки зрения ORM, "through_table" не существует. Он только определен, поэтому он может создать SQL, необходимый для работы отношения. Это также означает, что дополнительные поля в сквозной таблице не поддерживаются, они могут содержать только ключевые значения.
Если вам нужны атрибуты (дополнительные столбцы) в сквозной таблице, она станет стандартной таблицей в вашей базе данных, для которой требуется модель. Ваше отношение "многие-2-многие" затем распадается на два отношения "один-два-много".
Обратите внимание, что оба могут существовать в одно и то же время, поэтому вы все равно можете использовать "многие ко многим", если вам не нужно запрашивать или использовать столбцы в сквозной таблице.