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

これにより、Magentoの外部で実行した場合に完全に正常に実行され、期待される結果が生成される次のSQLが生成されます。

[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句」の不明な列「DIF_AU」

また、having句を削除すると(結果が壊れる)、GridのデータソースにDIF_AU列を使用できます。


1
更新:親のgetSelectCountSql()メソッドの問題を追跡できました。これは、実際にコレクションカウントを取得しようとしたときに問題が発生している場所です。
アンソニーリーチジュニア

1
回答を投稿してください!WTHはそれsd_order_typeから来ているのですか?
ベンマーク

1
フラットテーブルに追加された極秘カスタムオーダータイプのもの。私はまだ答えを練っています。
アンソニーリーチジュニア

1
「評価が10未満のユーザーは、質問してから8時間は自分の質問に答えることができません。7時間以内に答えることができます。それまではコメントを使用するか、質問を編集してください。」(7時間以内に解決する)。
アンソニーリーチジュニア

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()を拡張する必要があるかのように見えます。

カスタムコレクションクラスで拡張getSelectCountSql()を作成しました。これは、havingステートメントに必要な欠落している列に追加されます。


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 :)
ダビダルガー

バグレポートを提出してください!magentocommerce.com/bug-tracking
ベンマークス

これも私が見た問題であり、答えを見つけるのによくやった。ただし、あなたのソリューションが正しいとは思わない-あなたはgroup byを使用しているため、SelectCountSqlはグループの数を返す必要があります。したがって、count(fetchAll())が必要か、count(distinct main_table.entity_id)代わりにcount(*)
Benubird

おそらく正しいと思います。このプロジェクトは、この投稿以来、後回しにされており、今に戻っています。先週のデモで、グリッドで誤ったレコード数が報告されていることに気付きました。解決したら、調査結果を報告します。
アンソニーリーチジュニア

@AnthonyLeachJr調査結果に関するニュースはありますか?
サイモン

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

PS:この回答は、一般的なmagentoコレクション用です。製品コレクションのみに関連するものではありません。


0

これは働いています

public function 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.