使ってみます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
このように動作します:
最初のパラメータは式(仮想フィールド名)の別名です。
2番目のパラメーターは式です。フィールド名をラップされたプレースホルダーで置き換え{{...}}
ます3番目のパラメーターは、プレースホルダーの対応です(なし{{}}
)。あなたの場合、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);