列名不明确的where子句冲突


28

对此有一点背景。我想扩展销售订单导出功能(通过网格)以具有更多列。我创建了一个模块,该模块添加了用于导出的新网格以及扩展原始模型的新集合模型。这使用_beforeLoad()函数,因此我可以联接所需的表。

我遇到的麻烦是,当添加了来自网格的过滤器(increment_id,订购日期等)时,此添加的where子句没有为表添加前缀,并且我遇到了列名不明确的问题。例如,在crement_id上,where子句中存在问题:

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()函数中的其他表之前,添加了where子句。

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();
}

我必须使用增量ID来连接销售订单网格表和SagePay交易表,因为这是我可以看到的唯一通用ID。

基本上,我想知道最好的方法是解决这个问题。我可能可以摆脱上面提到的更改,但是感觉不对。我可以在join语句中进行任何更改吗?

谢谢。


1
您是如何加入餐桌的?在Zend_Db_Select模型上工作不是一个好主意,因为magento记录联合表并通常添加所有前缀。我写了一篇博客文章有关的加盟,也许它可以帮助:blog.fabian-blechschmidt.de/articles/...
法比安布莱赫施密特

谢谢您的回应,我会读一读。我尝试使用joinTable(),但在收集模型中不可用。
2013年

Answers:


52

您可以使用以下收集方法轻松解决任何歧义的where条件:

  • addFilterToMap($filterName, $alias, $group = 'fields')
    • $filter-这是在addFieldToFilter()方法中使用的过滤器的名称,对于您的情况是increment_id
    • $alias-它是与过滤器关联的列的全名,对于您而言,它是main_table.increment_id
    • $group -本来打算作为集合中任何类型信息的映射,但目前仅在过滤器中使用,因此您可以忽略此参数。

另外,除非您观察到一个事件,否则我不认为beforeLoad是放置联接的正确位置。在您的情况下,最好_initSelect()使用before调用将其移入方法parent::_initSelect()。您可以在addFilterToMap()方法内部调用方法_initSelect()来解决连接冲突,如下所示:

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

出于兴趣,为什么最好在_initSelect()中进行联接?
2013年

@Paul _initSelect始终只执行一次,_beforeLoad可以再调用一次,因为load()如果重置其状态,则可以多次收集。
Ivan Chepurnyi

以及@Paul,由于_beforeLoad可以被调用两次,因此您将在第二次调用时收到Zend_Db_Select的致命错误。
Ivan Chepurnyi 2013年

2
我做了这样的事情: $collection = Mage::getModel("education/ticket") ->getCollection() ->addFilterToMap('updated_at', 'main_table.updated_at') ->addFilterToMap('created_at', 'main_table.created_at');
FosAvance

@IvanChepurnyi,太有才了。它反映出您作为Magento 1架构师非常出色
阿米特·贝拉
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.