Оставьте присоединиться к таблице по запросу коллекции

27

Я делаю следующее, чтобы вывести некоторые заказы из системы на экспорт:

$orders = Mage::getModel('sales/order')->getCollection()
    ->addFieldToFilter('status', $statusToExport)
    ->addFieldToFilter('store_id', $this->processingStoreId)
    ->addFieldToFilter('updated_at', array('gteq' => date('Y-m-d H:i:s', $lastSyncTime)));

Мне нужно что-то добавить туда, где он не экспортируется, если порядок entity_idв пользовательской таблице у меня есть. Если бы я использовал SQL, я бы сделал:

left join myTable as mt on main_table.entity_id = mt.entity_id
where mt.entity_id is null

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

Примечание: я попробовал

$orders = $orders->getSelect()
    ->joinLeft(
        array("t1" => $myTable),
        "main_table.entity_id = t1.entity_id",
        array("admin_field_id" => "t1.id")
    )
    ->where("t1.id is null")

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

Я чувствую, что упускаю что-то простое ...

РЕДАКТИРОВАТЬ

Хорошо, я попробовал это:

$orders->getSelect()
    ->joinLeft(
        array("t1" => $myTable),
        "main_table.entity_id = t1.entity_id",
        array("admin_field_id" => "t1.id")
    )
    ->where("t1.id is null");

Когда я повторяю, (string)$orders->getSelect()он возвращает запрос, который я ожидал, и не возвращает результатов, когда я его запускаю $ordersТем не менее, по-прежнему содержит предметы. Я думал, что это объединение должно было изменить коллекцию на этом этапе?

webnoob
источник

Ответы:

53

Чтобы изменить запрос, вы можете сделать

$collection->getSelect()->doWhateverYouWantWithSelectObject();
foreach($collection as $order) {} // order collection

Но чтобы присоединиться к столу, вы можете просто использовать $collection->joinTable()

joinTableсуществует только на Mage_Eav_Model_Entity_Collection, это означает: продукты, категории, заказы, счета, creditmemo, отгрузка, клиенты. (Спасибо @Fra за комментарий)

joinTable ()

Но у коллекций magento есть метод, joinTable()который мне понадобился 45 минут, чтобы выяснить, как он используется. Чтобы избежать этого для вас, я делюсь этим.

$productCollection->joinTable(
    array('bonus' => 'mycompany/bonus'), 'product_id=entity_id',
    array('bonus_id' => 'bonus_id')
);

Параметры:

public function joinTable($table, $bind, $fields = null, $cond = null, $joinType = 'inner')
  1. Таблица проста, это namespace/entityформат magento , который вы используете в своей конфигурации, моделях ресурсов и коллекции. Вы можете использовать массив форматаarray('alias' => 'namespace/entity')
  2. Привязка означает, что оператор ON в вашем SQL. Это была самая трудная часть, и я объясню это подробнее позже. Важно, чтобы ваш плоский стол ДО и ваш EAV-стол ПОСЛЕ знака равенства. Не используйте main_table.перед атрибутом. Magento сделает это за вас. Подробнее об этом позже.
  3. Поля это массив . Если вы используете строку вместо этого, вы получите это: Warning: Invalid argument supplied for foreach() in /var/www/magento-1.6.2.0/app/code/core/Mage/Eav/Model/Entity/Collection/Abstract.php on line 775. Вы можете использовать массив формата array('field1', 'field2', '...')илиarray('alias' => 'field1', '...')
  4. Состояние ** ГДЕ ON условие ** в SQL.
  5. JoinType. Я надеюсь, вы знаете, что это такое. Но у вас есть только выбор между левым и внутренним .app/code/core/Mage/Eav/Model/Entity/Collection/Abstract.php:793

Больше на эту тему

Фабиан Блехшмидт
источник
1
Спасибо за эту отличную информацию. Исходя из вашего первого пункта, не следует ли $orders->getSelect() ->joinLeft(array("t1" => $myTable), "main_table.entity_id = t1.entity_id", array("admin_field_id" => "t1.id")) ->where("t1.id is null")исключить элементы из моего текущего списка?
webnoob
Я думаю, что вы редактируете коллекцию после загрузки. просто подключитесь к своему сценарию с помощью xdebug и проверьте флаг isLoaded внутри модели
Фабиан Блехшмидт,
2
Стоит отметить, что метод joinTable доступен только для Mage_Eav_Model_Entity_Collection
Fra
1

Я нашел причину для этого.

Я хотел подсчет значений, прежде чем применить левое соединение, поэтому я добавил

$totalOrderCount = count($orders);

это, однако, вызвало загрузку коллекции, что, в свою очередь, означало игнорирование левого соединения, которое я делал дальше. Во время отладки _isCollectionLoadedФабиан посоветовал посмотреть на переменную.

Сейчас я делаю это вместо того, чтобы получить счет коллекции:

$countOrdersObjs = clone $orders;
$totalOrderCount = count($countOrdersObjs);
unset($countOrdersObjs);

Это позволяет мне считать результаты без загрузки $ordersколлекции.

Примечание: Пожалуйста, примените любые комментарии к посту Фабиана выше, так как он руководил мной в этом, но я чувствовал, что решение оправдывает его собственный ответ.

webnoob
источник