Wie füge ich ein dynamisches Feld zur Magento-Sammlung hinzu?
-
16-10-2019 - |
Frage
Ich habe eine Magento-Sammlung wie diese erstellt, um die Entfernung von Lat Long zu berechnen.
$collection = Mage::getModel('module/module')->getCollection()->addFieldToFilter('status',1);
$collection->getSelect()->columns(array('distance' => new Zend_Db_Expr("( 6371 * acos( cos( radians(23.0130648) ) * cos( radians( latitude ) ) * cos( radians( longitude) - radians(72.4909026) ) + sin( radians(23.0130648) ) * sin( radians( latitude ) ) ) )")))
->having('distance <10')
->order('distance ' . Varien_Db_Select::SQL_ASC);
Aber ich erhalte die Fehlermeldung SQLSTATE[42S22]:Spalte nicht gefunden:1054 Unbekannte Spalte „Distanz“ in „Having-Klausel“.
Wenn ich das Sammlungsobjekt ausdrucke, stimmt die Entfernungsberechnung.Also, was war das Problem?
Mein Problem ist ähnlich wie diese Frage Problem bei der Verwendung von „have“ in der Magento-Sammlung
Ich verwende die Paginierung für die Sammlung. Wenn ich die Paginierungsklasse entferne, funktioniert es perfekt.Aber ich kann das Problem mit der bereitgestellten Lösung nicht lösen.Hier ist mein Paginierungscode.
In _prepareLayout()
Funktion Ich habe das gesetzt
$pager = $this->getLayout()->createBlock('page/html_pager', 'pager');
$pager->setAvailableLimit(array(5=>5,10=>10,20=>20,'all'=>'all'));
$pager->setCollection($this->getCollection());
$this->setChild('pager', $pager);
$this->getCollection()->load();
return $this;
Fügen Sie diese Funktion auch in der Blockdatei hinzu
public function getPagerHtml()
{
return $this->getChildHtml('pager');
}
und nennen Sie dies in der HTML-Datei als <?php echo $this->getPagerHtml(); ?>
Lösung
Ich kann versuchen, es zu verwenden addExpressionFieldToSelect
.
Die Methode finden Sie in Mage_Core_Model_Resource_Db_Collection_Abstract
.
In Ihrem Fall sollte es ungefähr so aussehen:(Dies ist nur eine Annahme, es könnten einige Fehler auftreten, aber die Idee ist in Ordnung)
$collection = Mage::getModel('module/module')->getCollection()->addFieldToFilter('status',1);
$collection->addExpressionFieldToSelect('distance', '( 6371 * acos( cos( radians(23.0130648) ) * cos( radians( {{latitude}}) ) * cos( radians( {{longitude}}) - radians(72.4909026) ) + sin( radians(23.0130648) ) * sin( radians( {{latitude}}) ) ) )', array('latitude'=>'latitude', 'longitude'=>'longitude'));
$collection->getSelect()->having('distance > 10');
Der addExpressionFieldToSelect
funktioniert so:
Der erste Parameter ist der Alias des Ausdrucks (Name des virtuellen Felds).
Der zweite Parameter ist der Ausdruck.Ersetzen Sie die Feldnamen durch umschlossene Platzhalter {{...}}
Der dritte Parameter ist die Platzhalterkorrespondenz (ohne). {{}}
).In Ihrem Fall latitide
Platzhalter entspricht latitude
Feld also {{latitude}}
wird durch ersetzt latitude
.Das Gleiche gilt für longitude
.
[BEARBEITEN]
Es gibt ein Problem beim Hinzufügen einer Paginierung zum $collection
so was
$collection->setCurPage(1)->setPageSize(5);
Hier ist die Rückverfolgung des Problems.Wenn die Sammlung geladen wird, wird dies aufgerufen _renderLimit()
.Die Methode sieht so aus
protected function _renderLimit()
{
if($this->_pageSize){
$this->_select->limitPage($this->getCurPage(), $this->_pageSize);
}
return $this;
}
Das ruft also getCurPage()
(sehen Varien_Data_Collection
Klasse).
getCurPage
verfügt über eine zusätzliche Überprüfung, um festzustellen, ob die Seitenzahl nicht außerhalb des maximalen Bereichs liegt, und berechnet so die Gesamtzahl der Seiten darin getLastPageNumber()
.
Das Problem hierbei ist, dass Magento die Spalten in der Auswahl zur Berechnung der Sammlungsgröße zurücksetzt.In Varien_Data_Collection_Db::getSelectCountSql
da ist das:
$countSelect->reset(Zend_Db_Select::COLUMNS);
Durch Zurücksetzen der Spalten erhalten Sie diese SQL
SELECT COUNT(*) FROM `table_name_here` AS `main_table` HAVING (distance < 10)
Dies ist es, was den Fehler erzeugt.
Ich sehe hier 2 Möglichkeiten.
Sie überschreiben in Ihrer Sammlungsklasse die Methode
getSelectCountSql
und entfernen Sie die Spalte zurückgesetzt: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);//comment this line $countSelect->columns('COUNT(*)'); return $countSelect; }
Sie überschreiben die
getCurPage()
Methode zum Überspringen der Bereichsvalidierung:public function getCurPage($displacement = 0){ if (!empty($this->_curPage)){ return $this->_curPage + $displacement; } return 1; }
[BEARBEITEN ZUM BEARBEITEN]
Um zu vermeiden, dass sich dies auf die übrigen Module auswirkt, können Sie das überschreiben getCurPage
Methode wie diese:
public function getCurPage($displacement = 0){
if (!$this->getDirectCurPage()){//if a specific flag is not set behave as default
return parent::getCurPage($displacement);
}
if (!empty($this->_curPage)){
return $this->_curPage + $displacement;
}
return 1;
}
Nun, wenn Sie Ihre verwenden möchten having
Methode fügen Sie dies einfach Ihrer Sammlung hinzu
$collection->setDirectCurPage(1);
Andere Tipps
Versuchen Sie es stattdessen:
$collection = Mage::getModel('module/module')->getCollection()->addFieldToFilter('status',1);
$collection->getSelect()->columns(array('distance' => new Zend_Db_Expr("( 6371 * acos( cos( radians(23.0130648) ) * cos( radians( latitude ) ) * cos( radians( longitude) - radians(72.4909026) ) + sin( radians(23.0130648) ) * sin( radians( latitude ) ) ) )")))
->addAttributeHaving('distance <10')
->addAttributeToSort('distance', Varien_Db_Select::SQL_ASC);
Du könntest es versuchen where()
Anstatt von having()
Wie Sie keine verwenden JOIN
Aussagen:
$collection->getSelect()->where('distance > ?', 10);