我正在寻找更好的解决方案来解决这类问题。我需要对具有许多搜索选项的公寓进行高级搜索:关键字,类别,日期,日期,价格范围(价格最低,最高价格)以及其他字段...... 如果您选择两个日期,我会计算每间公寓的租金。要计算价格,我不能使用virtualField或一个或多个子查询,但我必须使用模型Apartment的函数,因为它执行了许多计算......
所以我决定使用回调afterFind计算租金价格并在查询结果数组中添加“column”rental_price:
public function afterFind($results, $primary){
if($this->dateFrom && $this->dateTo){
foreach ($results as $key => $val) {
if(isset($val['Apartment']['id'])){
$results[$key]['Apartment']['rental_price'] = $this->calculateRentalPrice($val['Apartment']['id'], $this->dateFrom, $this->dateTo);
}
}
}
return $results;
}
在控制器上:
$this->paginate = array( ... ); // Array with the query
$apartments = $this->paginate('Apartment');
// EDIT
foreach ($apartments as $key => &$apartment) {
if($apartment['Apartment']['rental_price'] < $priceMin || $apartment['Apartment']['rental_price'] > $priceMax){
unset($apartments[$key]);
}
}
$this->set('apartments', $apartments);
问题在于,现在我想以最低价格和最高价格重新过滤数组$公寓,但如果我直接操纵$ apartments我有分页问题。 解决这种情况的最佳方法是什么?
// EDIT
public function calculateRentalPrice($apartmentId, $dateFrom, $dateTo){
$from = new DateTime($dateFrom);
$to = new DateTime($dateTo);
$period = new DatePeriod($from, DateInterval::createFromDateString('1 day'), $to);
$rentalPrice = 0;
foreach ($period as $day){
$date = $day->format("Y-m-d");
$dailyPrice = $this->ApartmentSeason->getDailyPrice($apartmentId, $date);
$rentalPrice += $dailyPrice;
}
return $rentalPrice;
}
public function getDailyPrice($apartmentId, $date){
$apartmentSeason = $this->find('first', array(
'conditions' => array(
'ApartmentSeason.apartment_id' => $apartmentId,
"'{$date}' BETWEEN ApartmentSeason.date_from AND ApartmentSeason.date_to",
"ApartmentSeason.date_to != " => $date,
)
));
$dailyPrice = $apartmentSeason['ApartmentSeason']['price'] / 7;
return $dailyPrice;
}
答案 0 :(得分:0)
解决此问题的一种方法是将每个价格的模型绑定在日期范围内,然后在虚拟字段中将它们合计。可能有更优雅的方法来解决这个问题,但我想不出一个不使用程序的方法。这也可以分成可重复使用的可测试部件。
$from = new DateTime($this->dateFrom);
$to = new DateTime($this->dateTo);
$period = new DatePeriod($from, DateInterval::createFromDateString('1 day'), $to);
$i = 0;
$sums = array();
// bind a new model for each "season" price
foreach ($period as $day) {
$date = $day->format("Y-m-d");
// create a new alias
$alias = "ApartmentSeasonPrice$i";
$params = array(
'className' => 'ApartmentSeason',
'foreign_key' => 'apartment_id',
'conditions' => array(
"'{$date}' BETWEEN $alias.date_from AND $alias.date_to",
"$alias.date_to != " => $date
);
// attach the model
$this->Apartment->bindModel(array(
'hasOne' => array(
$alias => $params;
)
));
// save the column we want to sum
$sums[] = "$alias.price";
}
// total them up in a virtual field
$this->Apartment->virtualFields['rental_price'] = 'COALESCE(SUM('+implode(',', $sums).', 0))';
// paginate
$this->set('apartments', $this->paginate());