CakePHP 3通过ambigious列错误的分页顺序?

时间:2016-02-19 16:09:26

标签: cakephp pagination cakephp-3.0

当我尝试将条件传递给匹配函数,将Tasks与Projects匹配时,分页器传递 ORDER BY 删除Table对象并导致该列具有不确定性。

这是一个错误还是有人知道这是怎么发生的?

匹配

if($groupFilter)
{
    // Filtering by group
    $projects = $this->Projects->find('all')->where($wheres)
        ->matching('Tasks', function ($q) use ($groupFilter) {
            return $q->where(['Tasks.group_id' => $groupFilter, 'Tasks.removed' => 0])->order(['Tasks.deadline ASC', 'Tasks.created ASC']);
                })
        ->contain(['Customers','Tasks.Users'])->distinct(['Projects.id']);
}
else
{
    // Groupfiltering is not set, filter normally.
    $projects = $this->Projects->find('all')->contain(['Customers'])->where($wheres)->contain([
        'Tasks',
        'Tasks.Users'
    ]);
}

PAGINATE

$this->paginate = [
    'sortWhitelist' => [
            'Projects.name', 'Customers.name', 'Projects.deadline IS NULL', 'Projects.tasks_active', 'Projects.tasks_used_hours', 'Projects.deadline'
    ],
    'order' => [
        'Projects.deadline IS NULL' => 'ASC', 
        'Projects.deadline' => 'ASC'
    ],
    'limit' => 50
];
$this->set('projects', $this->paginate($projects));

SQL

SELECT projects.id                        AS `Projects__id`, 
       projects.customer_id               AS `Projects__customer_id`, 
       projects.user_id                   AS `Projects__user_id`, 
       projects.name                      AS `Projects__name`, 
       projects.description               AS `Projects__description`, 
       projects.deadline                  AS `Projects__deadline`, 
       projects.status                    AS `Projects__status`, 
       projects.tasks_total               AS `Projects__tasks_total`, 
       projects.tasks_active              AS `Projects__tasks_active`, 
       projects.tasks_completed           AS `Projects__tasks_completed`, 
       projects.tasks_allocated_hours     AS `Projects__tasks_allocated_hours`, 
       projects.tasks_used_hours          AS `Projects__tasks_used_hours`, 
       projects.tasks_used_hours_nondebit AS 
       `Projects__tasks_used_hours_nondebit`, 
       projects.created                   AS `Projects__created`, 
       tasks.id                           AS `Tasks__id`, 
       tasks.create_user_id               AS `Tasks__create_user_id`, 
       tasks.responsible_user_id          AS `Tasks__responsible_user_id`, 
       tasks.user_id                      AS `Tasks__user_id`, 
       tasks.customer_id                  AS `Tasks__customer_id`, 
       tasks.task_type_id                 AS `Tasks__task_type_id`, 
       tasks.group_id                     AS `Tasks__group_id`, 
       tasks.hour_bank_id                 AS `Tasks__hour_bank_id`, 
       tasks.contact_person_id            AS `Tasks__contact_person_id`, 
       tasks.helpdesk_task_id             AS `Tasks__helpdesk_task_id`, 
       tasks.name                         AS `Tasks__name`, 
       tasks.description                  AS `Tasks__description`, 
       tasks.amount                       AS `Tasks__amount`, 
       tasks.report_sum                   AS `Tasks__report_sum`, 
       tasks.amount_type                  AS `Tasks__amount_type`, 
       tasks.status                       AS `Tasks__status`, 
       tasks.invoice                      AS `Tasks__invoice`, 
       tasks.invoiced                     AS `Tasks__invoiced`, 
       tasks.created                      AS `Tasks__created`, 
       tasks.deadline                     AS `Tasks__deadline`, 
       tasks.project_id                   AS `Tasks__project_id`, 
       tasks.start                        AS `Tasks__start`, 
       tasks.prioritized                  AS `Tasks__prioritized`, 
       tasks.completed_at                 AS `Tasks__completed_at`, 
       tasks.removed                      AS `Tasks__removed`, 
       customers.id                       AS `Customers__id`, 
       customers.name                     AS `Customers__name`, 
       customers.api                      AS `Customers__api` 
FROM   projects Projects 
       INNER JOIN tasks Tasks 
               ON ( tasks.group_id = :c0 
                    AND tasks.removed = :c1 
                    AND projects.id = ( tasks.project_id ) ) 
       LEFT JOIN customers Customers 
              ON customers.id = ( projects.customer_id ) 
WHERE  projects.status = :c2 
GROUP  BY projects.id 
ORDER  BY deadline IS NULL ASC, // missing table
          projects.deadline ASC 
LIMIT  50 offset 0 

1 个答案:

答案 0 :(得分:1)

这些订单密钥不受支持,分页器前缀机制会偶然发现它,因为它需要Alias.field语法,并且将根据模型架构检查字段是否存在。

<强> https://github.com/cakephp/.../3.2.2/src/Controller/Component/PaginatorComponent.php#L345

为了能够使用这样的订单条款,您必须通过查询对象来应用它们。因此,您无法通过开箱即用的此类条款对用户进行排序,您必须实现从请求查询中抓取(并取消设置)sort值的机制,并应用它在查询上,如

$sort = $this->request->query('sort');
// you may want to choose a non-technical alias instead
if ($sort !== null && $sort === 'Projects.deadline IS NULL') {
    unset($this->request->query['sort']);

    $expression = $projects->newExpr()->isNull('Projects.deadline');
    if (strtoupper($this->request->query('direction')) === 'ASC') {
        $projects->orderAsc($expression);
    } else {
        $projects->orderDesc($expression);
    }
}