모호한 열 이름을 가진 where 절에서 충돌


28

이에 대한 약간의 맥락. 더 많은 열을 갖도록 판매 주문 내보내기 기능을 그리드를 통해 확장하고 싶습니다. 내보낼 새 그리드를 추가하고 원본을 확장하는 새 컬렉션 모델을 추가하는 모듈을 만들었습니다. 이것은 _beforeLoad () 함수를 사용하므로 필요한 테이블을 조인 할 수 있습니다.

내가 겪고있는 문제는 그리드의 필터가 추가 될 때 (increte_id, order date 등)이 추가되는 where 절이 테이블을 접두사로 사용하지 않아서 모호한 열 이름에 문제가 발생한다는 것입니다. 예를 들어, increment_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`

이 where 절은 _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();
}

내가 볼 수있는 유일한 공통 ID이므로 increment_id를 사용하여 판매 주문 그리드 테이블과 SagePay 트랜잭션 테이블을 조인해야합니다.

기본적으로 나는 이것을 해결하는 가장 좋은 방법이 무엇인지 궁금합니다. 위에서 언급 한 변경 작업을 수행하지 않아도 될 수도 있지만 옳지 않습니다. 조인 선언문에서 변경할 수있는 것이 있습니까?

감사.


1
테이블을 어떻게 조인 했습니까? magento가 관절 테이블을 기록하고 모든 접두사를 정상적으로 추가하기 때문에 Zend_Db_Select 모델 작업은 좋지 않습니다. : 나는 어쩌면 도움 가입에 대한 블로그 기사를 쓴 blog.fabian-blechschmidt.de/articles/...
파비안 Blechschmidt

답변 주셔서 감사합니다, 나는 그것을 읽을 것입니다. joinTable ()을 사용하려고 시도했지만 컬렉션 모델에서 사용할 수 없었습니다.
Paul

답변:


52

다음 수집 방법을 사용하여 모호한 위치 조건을 쉽게 해결할 수 있습니다.

  • 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 ()에서 조인을 수행하는 것이 더 좋은 이유는 무엇입니까?
Paul

@Paul _initSelect은 항상 한 번만 실행되며 상태를 재설정하면 두 번 이상 수집 _beforeLoad할 수 있으므로 한 번 이상 호출 할 수 있습니다 load().
Ivan Chepurnyi

@Paul도 _beforeLoad를 두 번 호출 할 수 있으므로 두 번째 호출에서 Zend_Db_Select에서 치명적인 오류가 발생합니다.
Ivan Chepurnyi

2
나는 이렇게 $collection = Mage::getModel("education/ticket") ->getCollection() ->addFilterToMap('updated_at', 'main_table.updated_at') ->addFilterToMap('created_at', 'main_table.created_at');
몸부림 쳤다

@IvanChepurnyi, 정직합니다. 그것은 당신이 마 젠토 1 건축가
Amit Bera
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.