コレクションのgetSize()とcount()の違い


82

どちらも同じだと何度も聞いたことがあります。しかし、奇妙な問題に直面しています。CatalogSearchモジュールの製品コレクションでは、count()が正しい製品数を返しているのに対し、getSize()はゼロを返しています。

だから、基本的にこれは私が得ているものです:

$collection->count(); //correct count
$collection->getSize(); //0

ただし、検索ページにページネーションと製品を表示するかどうかを決定する際に、getSize()に正しいカウントが必要です。より具体的にするために、コレクションでのみ内部結合、左結合、およびWHERE条件を使用しています。

この奇妙な問題が発生する理由はありますか?

ありがとう

更新:

前の質問、Magentoでコレクションを複製する方法は?1つのコレクションで2つの異なる操作を実行したかった。最初のコレクションは正しいgetSize()を示していますが、getSize()がゼロの場合、WHERE句を削除して新しいWHERE条件を指定しました。この後、私は期待していた正しい生SQLを取得し、MySQLで実行すると正しいレコードセットも提供しますが、コレクションのgetSize()のみがゼロカウントを提供します。

そのため、getSize()が古いカウントを取得しているため、基本的にコレクションを再ロードする必要があります。理にかなっていますか?

回答:


84

ほとんどの(すべてではないにしても)コレクションが拡張されVarien_Data_Collection_Dbます。このクラスの2つのメソッドを次に示します

public function getSize()
{
    if (is_null($this->_totalRecords)) {
        $sql = $this->getSelectCountSql();
        $this->_totalRecords = $this->getConnection()->fetchOne($sql, $this->_bindParams);
    }
    return intval($this->_totalRecords);
} 

public function count() //inherited from Varien_Data_Collection
{
    $this->load();
    return count($this->_items);
}

違いがあります。以下のためにgetSize()コレクションセットされていません。それのcount()ためです。通常、コレクションモデルはgetSize()上記と同じメソッドを使用し、オーバーライドのみを行いますgetSelectCountSql()
getSelectCountSql()リミットセットフィルター(ために利用可能なレコードの合計数を取得するためにリセットされるwhere文)。どのように参照してくださいgetSelectCountSql()作品

public function getSelectCountSql()
{
    $this->_renderFilters();
    $countSelect = clone $this->getSelect();
    $countSelect->reset(Zend_Db_Select::ORDER);
    $countSelect->reset(Zend_Db_Select::LIMIT_COUNT);
    $countSelect->reset(Zend_Db_Select::LIMIT_OFFSET);
    $countSelect->reset(Zend_Db_Select::COLUMNS);
    $countSelect->columns('COUNT(*)');
    return $countSelect;
} 

3
すばらしいです!それでは、コレクションを再ロードして正しいコレクションを取得するための次のステップは何getSize()でしょうか?ありがとう!
MagExt

正直に言って、なぜこの結果が得られるのかわかりません。ではCatalogSearchモジュールよりも優先されます何もありませんgetSize()getSelectCountSql()。カスタムコードを追加しない限り、デフォルトで動作するはずです。コレクションの作成方法を投稿できますか?
マリウス

質問を更新しました。
MagExt

3
リセットする方法はありません_totalRecordsgetSize()元のコレクションを呼び出す前に、コレクションの複製を試みることができます。多分それはうまくいくでしょう。
マリウス

「リセット」カウントを取得するには、次のようなこともできます$sql = $collection->getSelectCountSql(); return $collection->getConnection()->fetchOne($sql);
。– koosa

14

注意してください。これは正しいですが、メソッドはVarien_Data_Collection_Dbマリウスによって説明されているように上書きされます

ただ見てください

// \Varien_Data_Collection::getSize
public function getSize()
{
    $this->load();
    if (is_null($this->_totalRecords)) {
        $this->_totalRecords = count($this->getItems());
    }
    return intval($this->_totalRecords);
}

// \Varien_Data_Collection::count
public function count()
{
    $this->load();
    return count($this->_items);
}

したがって、この低レベルでも同じである必要があります。どちらの方法でもコレクションをロードし、アイテムをカウントします。

更新

ああ、問題があります:getSize()は_totalRecordsをキャッシュします。これは再計算されないことを意味します。_totalRecords設定場所を確認しますか?


はい、私はそれを見ましたが、両方が同じコレクションに対して異なるカウントを生成している理由を理解できませんか?コレクションや何かを再読み込みして正しいカウントを取得する方法はありgetSize()ますか?
MagExt

エントリ更新
ファビアンBlechschmidt

1
getSize()データベースから取得したレコードのコレクションをロードしません。メソッドをオーバーライドして、コレクションをロードするように指示しない限り、そうではありません。
マリウス

_totalRecordsは保護されているため、コレクションを使用してカスタムファイルで呼び出すことはできません。echo count($collection->load()->getItems());正しい数を与えますが、再び私getSize()は働きたいです。
MagExt

5

この答えは「magento getSize wrong」と同様の検索でGoogleに表示されるので、誰かに役立つ可能性のあるシナリオを追加したいと思います

クエリにグループステートメントがあり、実行する場合

SELECT COUNT(DISTINCT e.entity_id) ... GROUP BY ( at_id_art.value )

Mysqlはグループごとにカウントを返すため、Varien_Data_Collection_Db :: getSize()は間違った答えを返します。これは、この関数が最初の行をフェッチするためです。

public function getSize()
{
    if (is_null($this->_totalRecords)) {
        $sql = $this->getSelectCountSql();
        $this->_totalRecords = $this->getConnection()->fetchOne($sql, $this->_bindParams);
    }
    return intval($this->_totalRecords);
}

移入するとき

$this->_totalRecords = $this->getConnection()->fetchOne($sql, $this->_bindParams);

最初の行を選択するため、最初のグループの合計が合計サイズとして返されます。

クエリ内の属性の一意の値に基づいて、カウントするこのコードを思い付きました。

$select = clone $collection->getSelect();
$group = $select->getPart(Zend_Db_Select::GROUP);
$select->reset(Zend_Db_Select::GROUP)->reset(Zend_Db_Select::COLUMNS)->columns("COUNT(DISTINCT {$group[0]})");
$totalCount = $collection->getConnection()->fetchOne($select);

2

ここにたどり着いた場合に備えて、試してみるべき別の簡単な修正方法があります。

System -> Index Management

それらをすべて選択し(「グリーン、インデックスの再作成は不要」と表示されている場合でも)、インデックスの再作成を強制します。

これにより、私の空のgetSize()問題が解決しました。これにより、特別および新規データベースリクエストが製品を検索し、「if」条件を満たし、適切にレンダリングすることができました。


0

製品に対して私が持っていたcount($collection)もの$collection->getSize()と異なるときはreindex、すべてがうまくいきました。


-1

主な違いがありますgetSize()の場合、製品コレクションはロードされません。count()の場合、製品コレクション全体をロードします。そのため、大きなカタログの場合、どのコレクションでもcount関数を使用することはお勧めできません。


マリウスの投稿ですでに述べています...
sv3n
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.