【问题标题】:CakePHP: How to make the paginator component use distinct counting?CakePHP:如何使分页器组件使用不同的计数?
【发布时间】:2018-05-25 04:38:36
【问题描述】:

我正在使用此代码进行简单的分页:

$paginate = array(
    'limit' => 30,
    'fields' => array('DISTINCT Doctor.id','Doctor.*'),
    'order' => array('Doctor.id' => 'desc'),
    'joins' => array(
        array('table' => 'doctors_medical_degrees',
            'alias' => 'DoctorsMedicalDegree',
            'type' => 'INNER',
            'conditions' => array(
                'Doctor.id = DoctorsMedicalDegree.doctor_id',
            )
        ),
    ),
    'recursive' => -1,
);
$this->Paginator->settings = $paginate;
$data = $this->Paginator->paginate('Doctor');

现在的问题是我使用的是内连接,所以对于 Distinct 结果我使用的是 Distinct Doctor.id,但是 cakephp 在查询分页时计数查询不包括 Distinct Doctor.id

'query' => 'SELECT COUNT(*) AS `count` FROM `pharma`.`doctors` AS `Doctor` INNER JOIN `pharma`.`doctors_medical_degrees` AS `DoctorsMedicalDegree` ON (`Doctor`.`id` = `DoctorsMedicalDegree`.`doctor_id`)'

如你所见,没有

COUNT(DISTINCT Doctor.id)

所以分页返回更多的结果,它实际上可以返回

【问题讨论】:

  • 请务必提及您的确切 CakePHP 版本!
  • 我使用的是 CakePHP 2.4.3 版,感谢您的建议。

标签: cakephp pagination


【解决方案1】:

问题是分页器没有将字段传递给find('count') 调用,所以默认情况下它总是依赖*

但即使它会传递字段,传递数组也会使find('count') 调用期望要计数的字段作为COUNT() 表达式传递,即类似于

'fields' => array('COUNT(DISTINCT Doctor.id) as `count`')

但是无论如何,这对分页器不起作用,所以您需要一个自定义的 find('count') 调用。

自定义查询分页救援

请参阅 Cookbook > Pagination > Custom Query Pagination 了解更多信息。

自定义查询分页可能是您最好的选择,这样计数的方式完全取决于您。

例如,您可以利用分页器组件传递的额外值,这样您就可以将要计数的字段传递给 find('count')` 调用,如下所示(未经测试的示例代码):

class Doctor extends AppModel {
    // ...

    public function paginateCount($conditions = null, $recursive = 0, $extra = array()) {
        $parameters = compact('conditions');
        if($recursive != $this->recursive) {
            $parameters['recursive'] = $recursive;
        }

        if(!empty($extra['countField'])) {
            $parameters['fields'] = $extra['countField'];
            unset($extra['countField']);
        }

        return $this->find('count', array_merge($parameters, $extra));
    }
}
$this->Paginator->settings = array(
    'limit' => 30,
    'fields' => array('DISTINCT Doctor.id','Doctor.*'),
    // ...
    'countField' => 'DISTINCT Doctor.id'
);
$data = $this->Paginator->paginate('Doctor');

这应该会创建一个看起来像这样的COUNT 查询

SELECT COUNT(DISTINCT Doctor.id) AS `count` ...

【讨论】:

  • 在此之前感谢我使用 group by 来实现 DISTINCT 结果。
【解决方案2】:

我在CakePHP - Pagination total count differs from actual count when using DISTINCT 上找到了解决方案 在模型中添加公共函数 paginateCount 并在分页器中使用 distinct 选项,例如:

$this->paginate = array('limit' => $limit, 'order' => array('Item.created' => 'ASC', 'Item.code' => 'ASC'),
            'fields' => 'DISTINCT Item.*',
            'conditions' => $conditions,
            'countField'   => array('Item.id'),
            'joins' => $joins,
            'distinct' => 'Item.id',
            'contain' => array(
                'Image' => array('limit' => 1),
                'ItemsTag'
                )
            );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-19
    • 1970-01-01
    • 2015-08-26
    • 2015-02-27
    相关资源
    最近更新 更多