我在用户模型中自定义查找类型方法:
protected function _findStats($state, $query, $results = array()) {
if ($state === 'before') {
debug($query);
$query['fields'] = array('User.id', 'User.username', 'Click.clicks', 'Click.unique', 'Sale.sales_1', 'Sale.sales_2');
$query['joins'] = array(
array(
'table' => '(' . $this->__buildSubQueryClicks() . ')',
'alias' => 'Click',
'type' => 'LEFT',
'conditions' => array('User.id = Click.id')
),
array(
'table' => '(' . $this->__buildSubQuerySales() . ')',
'alias' => 'Sale',
'type' => 'LEFT',
'conditions' => array('User.id = Sale.id')
)
);
return $query;
}
return $results;
}
现在来自其他Controller(名为ReportsController
)我想对此查找的结果进行分页。我是这样做的:
public function admin_index() {
list($from, $to) = $this->_prepareCommonVariables();
$this->paginate = array('stats');
$this->User->recursive = 0;
$this->set('users', $this->paginate('User',
array(
'Click.created BETWEEN ? AND ?' => array($from, $to),
'Sale.sold BETWEEN ? AND ?' => array($from, $to)
),
array('User.username', 'Click.unique', 'Click.clicks', 'Sale.sales_1', 'Sale.sales_2')
));
}
问题是我只能按User.id
和User.username
字段(通常是用户字段)排序。即使我通过Controller::paginate()
的第三个参数指定了允许的字段,它也不起作用。 Paginator Helper
链接会生成正确的URL(例如/admin/reports/index/sort:Click.clicks/direction:asc
),但我在SQL查询中看不到ORDER BY部分。我已将debug($query)
放入_findStats()
,当字段为Click.clicks
时,$query['order']
为空。
答案 0 :(得分:1)
好的,我发现$ query也会回复'sort'和'direction'键。所以,这里是解决方案:
protected function _findStats($state, $query, $results = array()) {
if ($state === 'before') {
$query['fields'] = array('User.id', 'User.username', 'Click.clicks', 'Click.unique', 'Sale.sales_1', 'Sale.sales_2');
$query['joins'] = array(
array(
'table' => '(' . $this->__buildSubQueryClicks() . ')',
'alias' => 'Click',
'type' => 'LEFT',
'conditions' => array('User.id = Click.id')
),
array(
'table' => '(' . $this->__buildSubQuerySales() . ')',
'alias' => 'Sale',
'type' => 'LEFT',
'conditions' => array('User.id = Sale.id')
)
);
if (isset($query['sort'], $query['direction'])) {
$query['order'] = array($query['sort'] => $query['direction']);
}
return $query;
}
return $results;
}
当然这不是安全的解决方案,因为它省略了PaginatorComponent::validateSort()
。
答案 1 :(得分:0)
从问题中的代码 - 看起来你已经做了正确的事情。
分页器组件validates the sort order,如果它来自请求:
验证是否可以对$ object执行所需的排序。只有字段或 virtualFields可以进行排序。方向参数也将被消毒。最后 sort +方向键将转换为模型友好的订单键。
您可以使用白名单参数来控制哪些列/字段可用于排序。 这有助于防止用户在未编入索引的值上排序大型结果集。
如问题所示,传递白名单应允许跳过此逻辑,但如果不调试,则可能 }和$field
中的值。
请记住问题中的调用是管理路由 - 您可以放弃验证排序参数的“安全性”,只需从请求中明确设置排序顺序:
$whitelist