Как добавить динамическое поле в коллекции Magento?
-
16-10-2019 - |
Вопрос
Я создал одну коллекцию Magento, подобную этой, чтобы рассчитать расстояние от LAT Long.
$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);
Но я получаю ошибку SQLState [42S22]: столбец не найден: 1054 Неизвестный столбец «расстояние» в «имеющемся предложении».
Когда я печатаю расчет расстояния объекта коллекции. так в чем была проблема?
Моя проблема похожа, как этот вопрос Проблема с использованием «иметь» в коллекции Magento
Я использую лицензию на коллекции, если я удаляю класс страниц, то она работает идеально. Но я не могу решить с предоставленным решением. Вот мой код страгивания.
В _prepareLayout()
Функция я поместил это
$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;
Добавьте эту функцию также в файл блока
public function getPagerHtml()
{
return $this->getChildHtml('pager');
}
и позвоните в файл phtml как <?php echo $this->getPagerHtml(); ?>
Решение
Я могу попробовать использовать addExpressionFieldToSelect
.
Вы можете найти метод в Mage_Core_Model_Resource_Db_Collection_Abstract
.
В вашем случае это должно быть что -то вроде этого: (это просто предположение, вы можете получить некоторые ошибки, но идея в порядке)
$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');
А addExpressionFieldToSelect
работает так:
Первый параметр - псевдоним выражения (имя виртуального поля).
Второй параметр - это выражение. Замените имена поля на заполнители, обернутые {{...}}
Третий параметр - это соответствие заполнителя (без {{}}
) В твоем случае latitide
Заполнитель соответствует latitude
Поле так {{latitude}}
будет заменен на latitude
. Анкет То же самое касается longitude
.
РЕДАКТИРОВАТЬ
Есть проблема при добавлении лиц в $collection
как это
$collection->setCurPage(1)->setPageSize(5);
Вот обратная связь проблемы. Когда коллекция загружена, это называется _renderLimit()
. Анкет Метод выглядит так
protected function _renderLimit()
{
if($this->_pageSize){
$this->_select->limitPage($this->getCurPage(), $this->_pageSize);
}
return $this;
}
Итак, это вызывает getCurPage()
(видеть Varien_Data_Collection
учебный класс).
getCurPage
имеет дополнительную проверку, чтобы увидеть, не находится ли номер страницы за пределами максимального диапазона, поэтому он рассчитывает общее количество страниц в getLastPageNumber()
.
Проблема здесь в том, что Magento сбрасывает столбцы в выборе для расчета размера сбора. В Varien_Data_Collection_Db::getSelectCountSql
есть это:
$countSelect->reset(Zend_Db_Select::COLUMNS);
Сбросив столбцы, вы в конечном итоге с этим SQL
SELECT COUNT(*) FROM `table_name_here` AS `main_table` HAVING (distance < 10)
Это то, что генерирует ошибку.
Я вижу 2 варианта здесь.
Вы переопределяете в своем классе коллекции метод
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);//comment this line $countSelect->columns('COUNT(*)'); return $countSelect; }
Вы переопределяете
getCurPage()
Метод для пропуска проверки диапазона:public function getCurPage($displacement = 0){ if (!empty($this->_curPage)){ return $this->_curPage + $displacement; } return 1; }
Редактировать, чтобы редактировать
Чтобы не влиять на остальные модули, вы можете переопределить getCurPage
метод подобного:
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;
}
Теперь, когда вы хотите использовать свой having
Метод просто добавьте это в свою коллекцию
$collection->setDirectCurPage(1);
Другие советы
Попробуйте вместо этого использовать:
$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);
Вы могли бы попробовать where()
вместо having()
Как вы не используете JOIN
заявления:
$collection->getSelect()->where('distance > ?', 10);