Unterschied zwischen getSize () und count () bei der Auflistung

82

Ich habe oft gehört, dass beide gleich sind. Ich habe jedoch ein seltsames Problem: In der Produktsammlung des CatalogSearch-Moduls gibt count () die korrekte Produktanzahl zurück, während getSize () null zurückgibt.

Im Grunde ist es das, was ich bekomme:

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

Ich möchte aber, dass getSize () die richtige Anzahl hat, da es entscheidet, ob Paginierung und Produkte auf der Suchseite angezeigt werden oder nicht. Ich verwende Inner Join, Left Join und Where Bedingung nur in der Sammlung, um genauer zu sein.

Irgendwelche Ideen, warum ich dieses seltsame Problem bekomme?

Vielen Dank

AKTUALISIEREN:

Meine vorherige Frage: Wie klone ich die Sammlung in Magento? Ich wollte zwei verschiedene Vorgänge für eine Sammlung ausführen. Die erste Auflistung zeigt das korrekte getSize (), aber wenn das getSize () null ist, habe ich die WHERE-Klausel entfernt und die neue WHERE-Bedingung angegeben. Danach erhalte ich korrektes unformatiertes SQL, was ich erwartet habe, und wenn ich es in MySQL starte, werden auch die richtigen Datensätze angezeigt, aber nur getSize () in der Auflistung gibt null Zähler an.

Im Grunde muss ich die Sammlung möglicherweise neu laden, da getSize () die alte Zählung annimmt. Macht Sinn?

MagExt
quelle

Antworten:

84

Die meisten (wenn nicht alle) Sammlungen werden erweitert Varien_Data_Collection_Db. Hier sind die 2 Methoden aus dieser Klasse

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

Da ist ein Unterschied. Denn getSize()die Sammlung wird nicht geladen. Für count()es ist. In der Regel verwenden Sammlungsmodelle dieselbe getSize()Methode wie oben und setzen sie nur außer Kraft getSelectCountSql().
Im getSelectCountSql()Limit wird zurückgesetzt, um die Gesamtzahl der für die eingestellten Filter verfügbaren Datensätze zu erhalten ( whereStatement). Sehen Sie, wie das getSelectCountSql()funktioniert

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;
} 
Marius
quelle
3
Toll! Was sollte mein nächster Schritt sein, um die Sammlung neu zu laden, damit sie korrekt wird getSize()? Vielen Dank!
MagExt
Ich weiß ehrlich gesagt nicht, warum Sie dieses Ergebnis erhalten. Im CatalogSearchModul gibt es nichts, was übersteuert getSize()oder getSelectCountSql(). Es sollte standardmäßig funktionieren, es sei denn, Sie haben benutzerdefinierten Code hinzugefügt. Können Sie die Art und Weise, wie Sie die Sammlung erstellen, veröffentlichen?
Marius
hat die Frage aktualisiert.
MagExt
3
Es gibt keine Möglichkeit zum Zurücksetzen _totalRecords. Sie können versuchen, die Sammlung zu klonen, bevor Sie getSize()die ursprüngliche Sammlung aufrufen . Vielleicht klappt das ja.
Marius
Sie können auch so etwas tun, um eine "Reset" $sql = $collection->getSelectCountSql(); return $collection->getConnection()->fetchOne($sql);
-Zählung
14

Achtung. Das ist richtig, aber die Methoden werden Varien_Data_Collection_Dbwie von Marius beschrieben überschrieben

Schauen Sie doch mal rein

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

Also sollte es auf diesem niedrigen Niveau dasselbe sein. Beide Methoden laden die Auflistung und zählen die Elemente.

AKTUALISIEREN

Oh, ich sehe ein Problem: getSize () speichert die _totalRecords zwischen, dies bedeutet, dass sie nicht neu berechnet werden. Überprüfen Sie, wo _totalRecordseingestellt ist?

Fabian Blechschmidt
quelle
Ja, ich habe es mir angesehen, kann aber nicht herausfinden, warum beide unterschiedliche Zählungen für dieselbe Sammlung generieren. Irgendwelche Ideen, wie man eine Sammlung neu lädt oder etwas, um die richtige Anzahl zu erhalten getSize()?
MagExt
hat den Eintrag
Fabian Blechschmidt
1
getSize()lädt die Sammlung für Datensätze, die aus der Datenbank stammen, nicht. Es sei denn, Sie überschreiben die Methode und weisen sie an, die Sammlung zu laden.
Marius
_totalRecords ist geschützt, kann also in meiner benutzerdefinierten Datei mit Sammlung nicht aufgerufen werden. echo count($collection->load()->getItems());gibt richtige Zählung, aber ich will getSize()wieder arbeiten.
MagExt
5

Diese Antwort wird in Google nach "magento getSize wrong" und ähnlichen Suchanfragen angezeigt. Daher möchte ich ein mögliches Szenario hinzufügen, das für jemanden nützlich sein könnte

Wenn Sie eine Gruppenanweisung in Ihrer Abfrage haben und eine

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

Mysql gibt eine Anzahl für JEDE der Gruppen zurück, also gibt Varien_Data_Collection_Db :: getSize () die falsche Antwort zurück. Dies liegt daran, dass diese Funktion die erste Zeile abruft:

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

Wenn es bevölkert

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

Es wählt die erste Zeile aus und gibt daher die Gesamtsumme der ersten Gruppe als Gesamtgröße zurück.

Am Ende habe ich mir diesen Code ausgedacht, um ihn zu zählen, basierend auf den eindeutigen Werten der Attribute in meiner Abfrage.

$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);
Wechselbalg
quelle
2

Für den Fall, dass Sie hier landen, gibt es eine weitere einfache Lösung:

System -> Index Management

und wählen Sie sie alle aus (auch wenn sie "Grün, keine Neuindizierung erforderlich" anzeigen) und zwingen Sie sie, neu zu indizieren.

Dies löste mein leeres getSize()Problem, das es den speziellen und neuen Datenbankanforderungen ermöglichte, die Produkte zu finden, die "Wenn" -Bedingungen zu erfüllen und richtig zu rendern.

BVRoc
quelle
0

Wann count($collection)war anders als $collection->getSize()ich zu reindexden Produkten, dann hat alles gut funktioniert.

Zsolti
quelle
-1

Es gibt einen Hauptunterschied Für getSize () wird die Produktkollektion nicht geladen. Für count () wird die gesamte Produktkollektion geladen. Für große Kataloge ist es daher nicht ratsam, die Zählfunktion in einer Sammlung zu verwenden.

Nayan Baraiya
quelle
Bereits in Marius Post gesagt ...
Sv3n