CakePHP 自定义字段未由分页器传递



我的PhotoalbumsModel中有这个方法

public function index_list()
{
$data = $this->find()
->contain(['Images' => function($q) {
$q->select([
'total' => $q->func()->count('image_id')
])
->group(['photoalbum_id']);
return $q;
}
]);
foreach ($data as $row)
{
$row->image_count = 0;
if (isset($row->images{0}->total))
{
$row->image_count = $row->images{0}->total;
}
unset($row->images);
}       
return $data;
}

这基本上是向行添加image_count

在我的控制器中,我使用:

<?php
class PhotoalbumsController extends AppController
{
public $paginate = [
'limit' => 2,
'order' => ['id' => 'desc']
];
public function index()
{
$photoalbums = $this->paginate($this->Photoalbums->index_list());
$this->set(compact('photoalbums'));
}

但是,在我看来,image_count并没有通过。不使用分页器,它就会被传递。

我该如何解决这个问题?

分页器将选项应用于查询,例如限制,这将导致查询被标记为脏,进而清除任何可能缓冲的结果集,因此您在那里所做的是迭代要删除的结果集,并修改将无处可去的对象(实体(。

你根本不应该依赖缓冲的结果集,如果你需要可靠地修改查询的结果,那么你应该使用结果格式化程序或map/reduce,它们在每次执行查询时都应用于结果:

$query = $this
->find()
->contain([
'Images' => function($q) {
$q
->select([
'total' => $q->func()->count('image_id')
])
->group(['photoalbum_id']);
return $q;
}
])
->formatResults(function (CakeCollectionCollectionInterface $results) {
return $results->map(function ($row) {
$row['image_count'] = $row['images'][0]['total'];
return $row;
});
});
return $query;

话虽如此,您也可以通过加入关联而不是包含关联并在主查询中选择列来直接在 SQL 级别处理此问题:

$query = $this->find();
$query
->select(['image_count' => $query->func()->count('Images.id')])
->enableAutoFields()
->leftJoinWith('Images')
->group('Photoalbums.id');

当然,还有计数器缓存行为。

参见

  • Cookbook> Database Access & ORM> Query Builder> Add Compute Fields
  • Cookbook> Database Access & ORM> 检索数据和结果集> 使用 Map/Reduce 修改结果
  • Cookbook> Database Access & ORM> Query Builder> Using leftJoinWith
  • Cookbook> Database Access & ORM> Behaviors> CounterCache

最新更新