Конфлікти, де пункт із неоднозначними назвами стовпців


28

Трохи контексту для цього. Я хочу розширити функцію експорту замовлення на продаж (через сітку), щоб було більше стовпців. Я створив модуль, який додає нову сітку для експорту, а також нову модель колекції, яка розширює оригінал. Для цього використовується функція _beforeLoad (), щоб я міг приєднатися до потрібних мені таблиць.

Проблема, яка у мене виникає, полягає в тому, що коли додаються фільтри з сітки (increment_id, дата замовлення тощо), додаток, який додається, не додає таблицю, і у мене виникають проблеми з неоднозначними назвами стовпців. Наприклад, у increment_id у мене виникає проблема в пункті, де:

SELECT `main_table`.*, `sales`.`total_qty_ordered`, `sales`.`entity_id` AS `order_id`, `sagepay`.`vendor_tx_code` FROM `sales_flat_order_grid` AS `main_table`
 LEFT JOIN `sales_flat_order` AS `sales` ON main_table.increment_id = sales.increment_id
 LEFT JOIN `sagepaysuite_transaction` AS `sagepay` ON order_id = sagepay.order_id WHERE (increment_id LIKE '%100000261%') GROUP BY `main_table`.`entity_id`

Цей пункт додається до того, як я приєднаюся до інших таблиць у функції _addColumnFilterToCollection ()

protected function _addColumnFilterToCollection($column)
    {
        if ($this->getCollection()) {
            $field = ( $column->getFilterIndex() ) ? $column->getFilterIndex() : $column->getIndex();
            if ($column->getFilterConditionCallback()) {
                call_user_func($column->getFilterConditionCallback(), $this->getCollection(), $column);
            } else {
                $cond = $column->getFilter()->getCondition();
                if ($field && isset($cond)) {
                    // Filter added at this point
                    $this->getCollection()->addFieldToFilter($field , $cond);
                }
            }
        }
        return $this;
    }

Як короткий тест, я змінив лінію на

$this->getCollection()->addFieldToFilter('main_table.' . $field , $cond);

і це спрацювало, але це не чудовий спосіб зробити це.

Мій код в _beforeLoad () є

protected function _beforeLoad()
{
    // Join the sales_flat_order table to get order_id and and total_qty_ordered
    $this->getSelect()->joinLeft(array('sales' => $this->getTable('sales/order')),
        'main_table.increment_id = sales.increment_id',
        array('total_qty_ordered' => 'sales.total_qty_ordered',
              'order_id' => 'sales.entity_id'));

    // Join the SagePay transaction table to get vendor_tx_code
    $this->getSelect()->joinLeft(array('sagepay' => $this->getTable('sagepaysuite2/sagepaysuite_transaction')),
        'order_id = sagepay.order_id',
        array('vendor_tx_code' => 'vendor_tx_code'));

    $this->getSelect()->group('main_table.entity_id');
    parent::_beforeLoad();
}

Мені доводиться використовувати increment_id, щоб приєднатися до таблиці сітки замовлень продажів та таблиці транзакцій SagePay, оскільки це єдиний загальний ідентифікатор, який я бачу.

В основному мені цікаво, який найкращий підхід для вирішення цього питання. Я, мабуть, міг би піти від зміни, про яку я згадував вище, але це не вірно. Чи можна щось змінити в заявах про приєднання?

Спасибі.


1
Як ви приєдналися до таблиць? Робота над моделлю Zend_Db_Select є поганою ідеєю, оскільки magento записує спільні таблиці та додає нормально всі префікси. Я написав статтю в блозі про приєднання, можливо, це допомагає: blog.fabian-blechschmidt.de/articles/…
Fabian Blechschmidt

Дякую за відповідь, я прочитаю це. Я намагався використовувати joinTable (), але він не був доступний у колекційній моделі.
Павло

Відповіді:


52

Ви можете легко вирішити будь-яку неоднозначну ситуацію, використовуючи наступний метод збору:

  • addFilterToMap($filterName, $alias, $group = 'fields')
    • $filter- це назва фільтра, який використовується в addFieldToFilter()методі, для вашого випадку цеincrement_id
    • $alias- це повне ім'я стовпця, яке пов'язане з фільтром, на ваш випадок це main_table.increment_id.
    • $group - мав бути картою для будь-якої інформації в колекції, але наразі вона використовується лише у фільтрах, тому цей аргумент можна опустити.

Крім того, я не думаю, що ранішеLoad - це правильне місце для приєднання, якщо ви не спостерігаєте за подією. У вашому випадку краще перейти до _initSelect()методу з викликом раніше parent::_initSelect(). Ви можете викликати addFilterToMap()метод всередині вашого _initSelect()методу для вирішення конфліктів приєднання, наприклад:

$this->addFilterToMap('increment_id', 'main_table.increment_id');

З-за інтересу, чому краще робити з'єднання в _initSelect ()?
Павло

@Paul _initSelectвиконується лише один раз весь час, _beforeLoadйого можна викликати більше одного разу, оскільки ви можете load()збирати не один раз, якщо скидаєте його стан.
Іван Чепурний

@Paul також, оскільки _beforeLoad можна викликати двічі, ви отримаєте фатальну помилку від Zend_Db_Select при другому дзвінку.
Іван Чепурний

2
Я робив таке: $collection = Mage::getModel("education/ticket") ->getCollection() ->addFilterToMap('updated_at', 'main_table.updated_at') ->addFilterToMap('created_at', 'main_table.created_at');
FosAvance

@IvanChepurnyi, Геніальний. Це свідчить про те, що ти прекрасний як архітектор Магенто 1
Аміт Бера
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.