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 'having clause'의 알 수없는 열 'DIF_AU'

또한 having 절을 제거하면 (결과가 깨짐) Grid의 데이터 소스에 DIF_AU 열을 사용할 수 있습니다.


1
업데이트 : 부모 getSelectCountSql () 메서드에 대한 문제를 추적 할 수있었습니다. 실제로 컬렉션 수를 얻으려고 할 때 문제가 발생합니다.
Anthony Leach Jr

1
답변을 게시하십시오! WTH는 sd_order_type어디에서 왔습니까?
benmarks

1
플랫 테이블에 추가 된 일급 비밀 사용자 정의 주문 유형 항목. 나는 여전히 답을 찾고 있습니다.
Anthony Leach Jr

1
"평판이 10 명 미만인 사용자는 요청 후 8 시간 동안 자신의 질문에 대답 할 수 없습니다. 7 시간 이내에 답변 할 수 있습니다. 그때까지 의견을 사용하거나 질문을 편집하십시오." (7 시간 안에 해결 될 솔루션).
Anthony Leach Jr

1
누군가이 사람에게
공감대를 주다

답변:


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 ()을 확장 해야하는 것처럼 보입니다.

have 문에 필요한 누락 된 열을 다시 추가하는 사용자 지정 컬렉션 클래스에서 확장 된 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
benmarks

이것은 또한 내가 본 문제이며 답변을 찾는 데 잘 수행되었습니다. 그러나 귀하의 솔루션이 옳지 않다고 생각합니다. 그룹별로 사용하고 있기 때문에 SelectCountSql은 그룹 수를 반환해야합니다. 당신이 카운트 하나를 필요 그래서 (fetchAll은 ()), 또는 사용하여 쿼리를 다시 작성하는 count(distinct main_table.entity_id)대신count(*)
Benubird

나는 당신이 정확하다고 생각합니다. 이 프로젝트는이 글 이후 백 버너에 있었고 지금 막 돌아 왔습니다. 지난 주 데모에서 그리드에 잘못된 레코드 수가보고 된 것을 발견했습니다. 해결 한 결과를 다시보고합니다.
Anthony Leach Jr

@AnthonyLeachJr 조사 결과에 대한 뉴스가 있습니까?
Simon

0

우선 컬렉션에서 $countSelect->reset(Zend_Db_Select::HAVING);재설정 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);

app / code / core / Mage / Catalog / Model / Resource / Product / Collection.php를 app / code / local / Mage / Catalog / Model / Resource / Product / 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;
}

추신 :이 답변은 일반적인 마 젠토 모음에 대한 것입니다. 제품 콜렉션에만 관련되지 않습니다.


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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.