Tôi có thể thử sử dụng addExpressionFieldToSelect.
Bạn có thể tìm thấy phương pháp trong Mage_Core_Model_Resource_Db_Collection_Abstract.
Trong trường hợp của bạn, nó phải là một cái gì đó như thế này: (Đây chỉ là một giả định, bạn có thể gặp một số lỗi, nhưng ý tưởng là 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');
Các addExpressionFieldToSelectcông việc như thế này:
tham số đầu tiên là bí danh của biểu thức (tên trường ảo).
Tham số thứ hai là biểu thức. Thay thế tên trường bằng giữ chỗ arround {{...}}
Tham số thứ ba là sự tương ứng giữ chỗ (không có {{}}). Trong trường hợp của bạn latitidegiữ chỗ tương ứng với latitudetrường vì vậy {{latitude}}sẽ được thay thế bằng latitude. Cùng đi cho longitude.
[EDIT]
Có một vấn đề khi thêm phân trang vào $collectionnhư thế này
$collection->setCurPage(1)->setPageSize(5);
Đây là nền tảng của vấn đề. Khi bộ sưu tập được tải, nó được gọi _renderLimit(). Phương pháp này trông như thế này
protected function _renderLimit()
{
if($this->_pageSize){
$this->_select->limitPage($this->getCurPage(), $this->_pageSize);
}
return $this;
}
Vì vậy, cuộc gọi này getCurPage()(xem Varien_Data_Collectionlớp).
getCurPagecó một xác minh bổ sung để xem nếu số trang không nằm ngoài phạm vi tối đa để nó tính tổng số trang trong đó getLastPageNumber().
Vấn đề ở đây là Magento đặt lại các cột trong phần chọn để tính kích thước bộ sưu tập. Trong Varien_Data_Collection_Db::getSelectCountSqlđó có cái này:
$countSelect->reset(Zend_Db_Select::COLUMNS);
Bằng cách đặt lại các cột, bạn kết thúc với sql này
SELECT COUNT(*) FROM `table_name_here` AS `main_table` HAVING (distance < 10)
Đây là những gì tạo ra lỗi.
Tôi thấy 2 lựa chọn ở đây.
Bạn ghi đè trong lớp bộ sưu tập của mình phương thức getSelectCountSql
và xóa thiết lập lại cột:
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;
}
Bạn ghi đè getCurPage()phương thức để bỏ qua xác thực phạm vi:
public function getCurPage($displacement = 0){
if (!empty($this->_curPage)){
return $this->_curPage + $displacement;
}
return 1;
}
[CHỈNH SỬA EDIT]
Để tránh ảnh hưởng đến các mô-đun còn lại, bạn có thể ghi đè getCurPagephương thức như sau:
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;
}
Bây giờ khi bạn muốn sử dụng havingphương thức của mình, chỉ cần thêm nó vào bộ sưu tập của bạn
$collection->setDirectCurPage(1);