Domanda

Ho creato una collezione di Magento come questo per la distanza calcolare dal lat lunga.

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

Ma sto errore SQLSTATE [42S22]: Colonna non trovato:. 1054 Unknown colonna 'distanza' a 'clausola having'

Quando stampo oggetto di raccolta Distanza calcolo è giusto. così quello che era il problema?

Il mio problema è simile come questa domanda con "avere" in collezione Magento

Sto usando l'impaginazione per la raccolta, se tolgo classe impaginazione allora funziona perfetto. Ma non sono in grado di risolvere con la soluzione fornita. Ecco il mio codice di impaginazione.

In funzione _prepareLayout() ho messo questo

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

aggiungere questa funzione anche nel file di blocco

  public function getPagerHtml()
  {
    return $this->getChildHtml('pager');
  }

e chiamare questo nel file di phtml come <?php echo $this->getPagerHtml(); ?>

È stato utile?

Soluzione

I può provare ad utilizzare addExpressionFieldToSelect.
È possibile trovare il metodo in Mage_Core_Model_Resource_Db_Collection_Abstract.
Nel tuo caso dovrebbe essere qualcosa di simile: (Questo è solo una supposizione, si potrebbe ottenere alcuni errori, ma l'idea è 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');

Il addExpressionFieldToSelect funziona così:
il primo parametro è l'alias dell'espressione (nome del campo virtuale).
Il secondo parametro è l'espressione. Sostituire i nomi dei campi con segnaposti avvolti arround {{...}}
Il terzo parametro è la corrispondenza segnaposto (senza {{}}). Nel tuo caso latitide segnaposto corrisponde al campo latitude così {{latitude}} sarà sostituito con latitude. Lo stesso vale per longitude.

[EDIT]
C'è un problema quando si aggiunge l'impaginazione alla $collection come questo

$collection->setCurPage(1)->setPageSize(5);  

Questa è la backtrace del problema. Quando la raccolta viene caricato questo si chiama _renderLimit(). Gli sguardi metodo come questo

protected function _renderLimit()
{
    if($this->_pageSize){
        $this->_select->limitPage($this->getCurPage(), $this->_pageSize);
    }

    return $this;
}

Quindi questo chiamate getCurPage() (vedere Classe Varien_Data_Collection).
getCurPage ha una verifica supplementare per vedere se il numero di pagina non è al di fuori della portata massima in modo che calcola il numero totale di pagine in getLastPageNumber().
Il problema è che Magento resetta le colonne della selezione per calcolare la dimensione di raccolta. In Varien_Data_Collection_Db::getSelectCountSql c'è questa:

$countSelect->reset(Zend_Db_Select::COLUMNS);

Per resettare le colonne si finisce con questo sql

SELECT COUNT(*) FROM `table_name_here` AS `main_table` HAVING (distance < 10)

Questo è ciò che genera l'errore.

Vedo 2 opzioni qui.

  1. Si sovrascrivere nella classe collezione il metodo getSelectCountSql e rimuovere il reset della colonna:

    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;
    }
    
  2. È l'override del metodo getCurPage() di saltare la convalida gamma:

    public function getCurPage($displacement = 0){
        if (!empty($this->_curPage)){
            return $this->_curPage + $displacement;
        }
        return 1;
    }
    

[Modifica per modificare]
Per evitare di compromettere il resto dei moduli è possibile ignorare il metodo getCurPage in questo modo:

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

Ora, quando si desidera utilizzare il metodo di having solo aggiungere questo alla vostra raccolta

$collection->setDirectCurPage(1);

Altri suggerimenti

Provare a utilizzare questo, invece:

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

Si potrebbe provare where() invece di having() come non si utilizza alcuna dichiarazione JOIN:

$collection->getSelect()->where('distance > ?', 10);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a magento.stackexchange
scroll top