Comment ajouter le champ dynamique dans la collecte de magento?
-
16-10-2019 - |
Question
J'ai créé une collection de magento comme celui-ci à la distance de latitude calculate longtemps.
$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);
Mais j'obtiens l'erreur SQLSTATE [42S22]: La colonne est introuvable. 1054 Unknown column 'distance' dans 'clause having'
Quand imprimer objet de collection calcul La distance est droit. alors quel était le problème?
Mon problème est similaire, comme cette question problème en utilisant « avoir » dans la collecte Magento
J'utilise sur la collecte de pagination, si je retire classe alors il fonctionne en page parfaite. Mais je suis incapable de résoudre avec une solution fournie. Voici mon code de pagination.
En fonction _prepareLayout()
je mets cette
$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;
ajouter cette fonction également dans le fichier bloc
public function getPagerHtml()
{
return $this->getChildHtml('pager');
}
et appeler ce fichier dans phtml comme <?php echo $this->getPagerHtml(); ?>
La solution
Je peux essayer d'utiliser addExpressionFieldToSelect
.
Vous pouvez trouver la méthode Mage_Core_Model_Resource_Db_Collection_Abstract
.
Dans votre cas, il devrait être quelque chose comme ceci: (Ceci est juste une hypothèse, vous pourriez obtenir quelques erreurs, mais l'idée est ok)
$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');
Le addExpressionFieldToSelect
fonctionne comme ceci:
le premier paramètre est l'alias de l'expression (nom du champ virtuel).
Le second paramètre est l'expression. Remplacer les noms des champs avec des espaces réservés enveloppées arround {{...}}
Le troisième paramètre est la correspondance de l'espace réservé (sans {{}}
).
Dans votre cas espace réservé latitide
correspond au champ de latitude
si {{latitude}}
sera remplacé par latitude
. Même chose pour longitude
.
[EDIT]
Il y a un problème lors de l'ajout à la pagination $collection
comme ceci
$collection->setCurPage(1)->setPageSize(5);
Voici la trace de la question.
Lorsque la collection est chargé ce qu'on appelle _renderLimit()
. La méthode ressemble à ceci
protected function _renderLimit()
{
if($this->_pageSize){
$this->_select->limitPage($this->getCurPage(), $this->_pageSize);
}
return $this;
}
Donc, ce appels getCurPage()
(voir classe Varien_Data_Collection
).
getCurPage
a une vérification supplémentaire pour voir si le numéro de page ne sont pas en dehors de la plage max il calcule le nombre total de pages dans getLastPageNumber()
.
Le problème ici est que Magento remet à zéro les colonnes de la sélection pour le calcul de la taille de la collection. En Varien_Data_Collection_Db::getSelectCountSql
il y a ceci:
$countSelect->reset(Zend_Db_Select::COLUMNS);
Par reseting les colonnes vous vous retrouvez avec cette sql
SELECT COUNT(*) FROM `table_name_here` AS `main_table` HAVING (distance < 10)
est ce qui génère l'erreur.
Je vois 2 options ici.
-
Vous override dans votre classe de collection la méthode
getSelectCountSql
et retirer la remise à zéro de la colonne: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; }
-
Vous substituez la méthode de
getCurPage()
sauter la validation de la plage:public function getCurPage($displacement = 0){ if (!empty($this->_curPage)){ return $this->_curPage + $displacement; } return 1; }
[EDIT TO EDIT]
Pour éviter d'affecter le reste des modules que vous pouvez remplacer la méthode getCurPage
comme ceci:
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;
}
Maintenant, quand vous voulez utiliser votre méthode having
simplement ajouter à votre collection
$collection->setDirectCurPage(1);
Autres conseils
Essayez d'utiliser ceci:
$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);
Vous pouvez essayer where()
au lieu de having()
que vous n'utilisez des déclarations de JOIN
:
$collection->getSelect()->where('distance > ?', 10);