Зліва приєднайтесь до таблиці за запитом колекції


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")

але це змінює його, так що це запит, і я хочу, щоб продажі / замовлення повернулися.

Я відчуваю, що мені не вистачає чогось простого ...

EDIT

Гаразд, я спробував це:

$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однак, все ще містить елементи. Я думав, що це приєднання має на увазі змінити колекцію в цей момент?

Відповіді:


53

Щоб змінити запит, який ви можете зробити

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

Але для приєднання до таблиці ви можете просто скористатися $collection->joinTable()

joinTableіснує лише на Mage_Eav_Model_Entity_Collection, це означає: товари, категорії, замовлення, рахунки, кредитні меморіали, доставки, клієнти. (Дякую @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. Bind означає, що оператор ON у вашому SQL. Це було найважче і я детально поясню це пізніше. Важливо мати свій плоский стіл ПЕРЕД, а свій стіл EAV ПІСЛЯ знака рівності. Не використовуйте main_table.перед атрибутом. Мадженто зробить це за вас. Детальніше про це пізніше.
  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. Умова - ** ДЕ Умова ВКЛ ** у 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 всередині моделі
Fabian Blechschmidt

2
Варто зазначити, що метод joinTable доступний лише для Mage_Eav_Model_Entity_Collection
Fra

1

Я знайшов причину цього.

Я хотів підрахувати значення, перш ніж застосувати ліве з'єднання, тому я додав

$totalOrderCount = count($orders);

це, однак, призвело до завантаження колекції, що, в свою чергу, означало, що вона ігнорує ліве з'єднання, про яке я робив далі. Поки налагодження, погляд на вар _isCollectionLoadedбув гарною порадою Фабіана.

Я зараз роблю це замість цього, щоб отримати кількість колекції:

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

Це дозволяє мені рахувати результати без завантаження $ordersколекції.

Примітка: Будь ласка, застосуйте будь-які надбавки до посту Фабіян вище, оскільки він керував мене на це, але я вважав, що рішення вимагає власної відповіді.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.