Випуск із використанням "маючи" у колекції Magento


20

Я намагаюся створити спеціальну колекцію для сітки в адміністративному модулі Magento. Я створив новий метод колекції під назвою "addAttributeHaving", який виконує наступні дії:

public function addAttributeHaving($value)
{
    $this->getSelect()->having($value);
    return $this;
}

Дивіться код колекції:

$collection->addFieldToSelect(
    array(
        'entity_id',
        'created_at',
        'increment_id',
        'customer_email',
        'customer_firstname',
        'customer_lastname',
        'grand_total',
        'status'
    )
);

$collection->getSelect()->joinLeft(array('sfop' => 'sales_flat_order_payment'), 'main_table.entity_id = sfop.parent_id', 'sfop.amount_authorized');
$collection->getSelect()->columns('sum(sfop.amount_authorized) AS AUTHD');
$collection->getSelect()->columns('grand_total - sum(sfop.amount_authorized) AS DIF_AU');
$collection->addFieldToFilter('main_table.state', array('in' => array('new','payment_review')));
$collection->addFieldToFilter('main_table.sd_order_type', array('neq' => 7));
$collection->addFieldToFilter('sfop.method', array('neq' => 'giftcard'));
$collection->addFieldToFilter('main_table.created_at', array('gt' => $this->getFilterDate()));
$collection->getSelect()->group(array('main_table.entity_id'));
$collection->addAttributeHaving('DIF_AU <> 0');
$collection->load(true,true);

$this->setCollection($collection);

Це створює наступний SQL, який ідеально чудово і дає очікувані результати, коли вибігаєте за межі Magento.

[METHOD=Varien_Data_Collection_Db->printLogQuery] SELECT `main_table`.`entity_id`, `main_table`.`entity_id`, `main_table`.`created_at`, `main_table`.`increment_id`, `main_table`.`customer_email`, `main_table`.`customer_firstname`, `main_table`.`customer_lastname`, `main_table`.`grand_total`, `main_table`.`status`, `sfop`.`amount_authorized`, sum(sfop.amount_authorized) AS `AUTHD`, grand_total - sum(sfop.amount_authorized) AS `DIF_AU` FROM `sales_flat_order` AS `main_table` LEFT JOIN `sales_flat_order_payment` AS `sfop` ON main_table.entity_id = sfop.parent_id WHERE (main_table.state in ('new', 'payment_review')) AND (main_table.sd_order_type != 7) AND (sfop.method != 'giftcard') AND (main_table.created_at > '2013-04-07') GROUP BY `main_table`.`entity_id` HAVING (DIF_AU <> 0)

Однак, коли я намагаюся завантажити сітку всередині Magento, я отримую таку помилку:

SQLSTATE [42S22]: стовпець не знайдено: 1054 Невідомий стовпець "DIF_AU" у "маючи пункт"

Крім того, якщо я видаляю застереження, яке має (яке порушує мої результати), я можу використовувати стовпчик DIF_AU для джерела даних у Grid.


1
ОНОВЛЕННЯ: Мені вдалося віднайти проблему до батьківського методу getSelectCountSql (). Це насправді там, де виникає проблема при спробі отримати кількість колекцій.
Ентоні Ліч-молодший

1
Опублікуйте відповідь! З чого це sd_order_typeпоходить?
орієнтири

1
Найпотаємніші спеціальні типи замовлення, додані до плоских столів. Я все ще опрацьовую відповідь.
Ентоні Ліч-молодший

1
"Користувачі з менш ніж 10 репутацією не можуть відповісти на власне запитання протягом 8 годин після запиту. Ви можете відповісти за 7 годин. До цього часу, будь ласка, використовуйте коментарі або редагуйте своє питання замість цього." (розчин надходить через 7 годин).
Ентоні Ліч-молодший

1
Хтось дає цій людині підсумок
1313

Відповіді:


12

Я збираюся насправді відповісти на власне запитання тут. Я знаю, липкий, але я натрапив на відповідь, коли дивився набагато ближче на фактичний слід стека. Колекція завантажується прекрасно, однак помилка настає трохи пізніше у виконанні, коли ми намагаємося отримати кількість колекцій у Varien_Data_Collection_Db :: getSelectCountSql () . SQL, який виробляється з цього, є:

SELECT COUNT(*) FROM sales_flat_order AS main_table LEFT JOIN sales_flat_order_payment AS sfop ON main_table.entity_id = sfop.parent_id WHERE (main_table.state in ('payment_review')) AND (main_table.sd_order_type != 7) AND (sfop.method != 'giftcard') AND (main_table.created_at > '2013-04-07') GROUP BY main_table.entity_id HAVING (DIF_AU <> 0)

Ви помітите, що оператор HAVING додається, але ми вже не маємо визначення для стовпця DIF_AU. Схоже, мені потрібно буде розширити користувацький getSelectCountSql () у моєму класі колекції, щоб отримати правильну кількість записів.

Я створив розширений getSelectCountSql () у користувальницькому класі колекції, який додає назад у відсутній стовпець, необхідний для оператора.


public function getSelectCountSql()
  {
    $countSelect = parent::getSelectCountSql();
    $countSelect->columns('grand_total - sum(sfop.amount_authorized) AS DIF_AU');
    $countSelect->reset(Zend_Db_Select::GROUP);
    return $countSelect;
  }

1
Зовсім не липко… Якщо ви спочатку розібраєтесь із рішенням, це рекомендується. Інші потенційно знайдуть це корисним у дорозі. +1 :)
davidalger

Ви повинні подати звіт про помилку! magentocommerce.com/bug-tracking
орієнтири

Це питання я також бачив, і це добре зроблено в пошуку відповіді. Однак я не думаю, що ваше рішення є правильним - оскільки ви використовуєте групу, ваш SelectCountSql повинен повертати кількість груп. Тож вам потрібно або порахувати (fetchAll ()), або переписати запит, використовуючи count(distinct main_table.entity_id)замістьcount(*)
Benubird

Я думаю, ви дуже вірогідні. Цей проект був на задній панелі з моменту цієї публікації, і тільки зараз повертаємось до неї. На демонстраційній версії минулого тижня я помітив неправильну кількість записів, повідомлених у сітці. Повідомляю про свої висновки, як тільки я це вирішу.
Ентоні Ліч-молодший

@AnthonyLeachJr якісь новини про ваші висновки?
Саймон

0

Перш за все $countSelect->reset(Zend_Db_Select::HAVING);це означає, що він буде скинутий HAVINGз вашої колекції. Це означає, що він видалить діюче застереження. І це не те, що ти хочеш. Ви можете додати його до колекції ( app/code/core/Mage/Catalog/Model/Resource/Product/Collection.php->_getSelectCountSql()тут)

Але головним винуватцем цього є getSize()метод, який існує у lib/Varien/Data/Collection/Db.phpфайлі.

Я спробував вищевказане рішення, згадане @Anthony, але це не спрацювало.

Тепер я зробив нижче.

public function getSize()
{
    if (is_null($this->_totalRecords)) {
        //$sql = $this->getSelectCountSql();
        $sql = $this->getSelect();
        $this->_totalRecords = count($this->getConnection()->fetchAll($sql, $this->_bindParams));
    }
    return intval($this->_totalRecords);
}

Перевірте, я навіть не використовую getSelectCountSql(). Я просто читаю весь запит SQL і отримую всі дані та повертаю їх кількість . Це все.


0

Я вирішив цю проблему тут: app / code / core / Mage / Catalog / Model / Resource / Product / Collection.php: 943 додати це: $ select-> reset (Zend_Db_Select :: HAVING);

Просто скопіюйте додаток / код / ​​core / Mage / Каталог / Модель / Ресурс / Продукт / Collection.php у додаток / код / ​​локальний / Mage / Каталог / Модель / Ресурс / Продукт / Collection.php

Мій код зараз виглядає так:

/**
 * Build clear select
 *
 * @param Varien_Db_Select $select
 * @return Varien_Db_Select
 */
protected function _buildClearSelect($select = null)
{
    if (is_null($select)) {
        $select = clone $this->getSelect();
    }
    $select->reset(Zend_Db_Select::ORDER);
    $select->reset(Zend_Db_Select::LIMIT_COUNT);
    $select->reset(Zend_Db_Select::LIMIT_OFFSET);
    $select->reset(Zend_Db_Select::COLUMNS);
    $select->reset(Zend_Db_Select::HAVING);

0

Це рішення спрацює, якщо у вашого вибору є унікальні назви стовпців, оскільки будь-які стовпці у списку вибору підзапиту повинні мати унікальні імена

Підзапит: підзапит таблиці дозволяє повторювати імена стовпців

public function getSelectCountSql()
{
    $this->_renderFilters();
    $select = clone $this->getSelect();
    $select->reset(Zend_Db_Select::ORDER);
    $select->reset(Zend_Db_Select::LIMIT_COUNT);
    $select->reset(Zend_Db_Select::LIMIT_OFFSET);        

    $countSelect = clone $this->getSelect();
    $countSelect->reset();
    $countSelect->from(array('a' => $select), 'COUNT(*)');
    return $countSelect;
}

PS: Ця відповідь стосується загальних колекцій магенто. не стосується лише колекції продукції.


0

Це працює

публічна функція getSize () {if (is_null ($ this -> _ totalRecords)) {// $ sql = $ this-> getSelectCountSql (); $ sql = $ this-> getSelect (); $ this -> _ totalRecords = count ($ this-> getConnection () -> fetchAll ($ sql, $ this -> _ bindParams)); } повернути intval ($ this -> _ totalRecords); }

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