Заказ на отношения "многие ко многим" с FuelPHP

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

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

Вот проблема, с которой я сталкиваюсь:

У меня есть модель "Item". Элементы могут иметь дочерние элементы (которые также являются элементами), соединенные через отношения "многие ко многим" через таблицу "items_items" с столбцом "parent_id" и "child_id". В таблице "items_items" также есть столбец "sortorder", так что порядок дочерних элементов может быть установлен.

Создание отдельной модели для этих отношений казалось мне излишним, поэтому заказ обновляется наблюдателем, который обновляет порядок сортировки дочерних элементов при сохранении родителя (методом "_event_after_save" на Model_Item). Кажется, это работает нормально.

Тем не менее, проблема, с которой я столкнулась, заключается в том, что я могу получить порядок сортировки, работающий либо с ленивой загрузкой, либо с активной загрузкой, но не с обоими. В зависимости от того, что работает, другой бросает топливные ошибки, поэтому единственный способ в настоящее время получать как нетерпеливую, так и ленивую загрузку для работы - это отказаться от предложения 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 выше, указав два отдельных отношения ("дети" и "ребенок") - один для активной загрузки, другой для ленивой загрузки, но он по-прежнему разбивает мое приложение, потому что он делает процесс удаления вызывает аналогичные ошибки. Я мог бы попытаться исправить это, но я чувствую, что это просто сбивает хак. Вместо этого я хотел бы создать надежный способ упорядочивания дочерних элементов, которые будут работать, будь они нетерпеливыми или ленивыми. Топливные документы предполагают, что это должно быть выполнимым (подход №1 выше), но я просто не могу заставить это работать...

Любая помощь будет очень высоко ценится!

2 ответа

Наконец-то мне удалось исправить эту проблему. Оказалось, что это проблема с текущей версией Fuel ORM (версия 1.7).

Что для меня работало, так это обновить ORM до более поздней версии разработки (60cc4eb576 на ветке ORM 1.8/develop), а затем установить "order_by" для отношения "многие ко многим" следующим образом:

...
'conditions' => array(
 'order_by' => array(
 'items_items.sortorder' => 'ASC'
 ),
)
...

Это комбинация подходов 2 и 3 выше, а не совсем синтаксис, который в настоящее время предлагает документация, но, похоже, работает как ожидалось/желательно как для eager-, так и для ленивой загрузки.


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

Если вам нужны атрибуты (дополнительные столбцы) в сквозной таблице, она становится стандартной таблицей в вашей базе данных, для которой требуется модель. Тогда ваше отношение "много-два" разбивается на два отношения "один-два".

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

licensed under cc by-sa 3.0 with attribution.