Cakephp 订购方式为';分页时无法使用自定义模型查找
我在用户模型中使用了自定义查找类型方法:Cakephp 订购方式为';分页时无法使用自定义模型查找,cakephp,cakephp-2.3,Cakephp,Cakephp 2.3,我在用户模型中使用了自定义查找类型方法: 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'
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;
}
现在从另一个控制器(名为reportscoontroller
)开始,我想对这个发现的结果进行分页。我是这样做的:
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()
的第三个参数指定了允许的字段,它也不起作用。paginatorhelper
链接生成正确的URL(例如/admin/reports/index/sort:Click.clicks/direction:asc
),但我在SQL查询中看不到按部分排序。我已将debug($query)
放入\u findStats()
中,当该字段为例如单击时,$query['order']
为空 按不存在的字段排序
从问题中的代码来看,看起来您已经在做正确的事情了
paginator组件(如果来自请求):
public function admin_index() {
list($from, $to) = $this->_prepareCommonVariables();
//$this->paginate = array('stats'); // <- not the right syntax
$settings = array('findType' => 'stats');
if (isset($this->request->params['named']['sort'])) {
$sortField = $this->request->params['named']['sort'];
$dir = $this->requestparams['named']['direction'];
$settings['order'] = array($sortField => $dir);
}
$this->paginate = $settings;
$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')
));
}
验证是否可以对$object执行所需的排序。只有字段或
virtualFields可以在上进行排序。方向参数也将被消毒。最后
排序+方向键将转换为模型友好的顺序键
您可以使用白名单参数来控制哪些列/字段可用于排序。
这有助于防止用户对未索引值的大型结果集进行排序
如问题所示,传递白名单应允许跳过此逻辑,但如果不调试分页器组件,则可能会发现$field
的名称与$whitelist
中的值之间存在某种不匹配
成为明确的作品
请记住,问题中的调用是一个管理路由-您可以放弃验证排序参数的“安全性”,只需根据请求显式设置排序顺序:
public function admin_index() {
list($from, $to) = $this->_prepareCommonVariables();
//$this->paginate = array('stats'); // <- not the right syntax
$settings = array('findType' => 'stats');
if (isset($this->request->params['named']['sort'])) {
$sortField = $this->request->params['named']['sort'];
$dir = $this->requestparams['named']['direction'];
$settings['order'] = array($sortField => $dir);
}
$this->paginate = $settings;
$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')
));
}
public function admin_index(){
list($from,$to)=$this->_prepareCommonVariables();
//$this->paginate=array('stats');//'stats');
if(isset($this->request->params['named']['sort'])){
$sortField=$this->request->params['named']['sort'];
$dir=$this->requestparams['named']['direction'];
$settings['order']=array($sortField=>$dir);
}
$this->paginate=$settings;
$this->User->recursive=0;
$this->set('users'),$this->paginate('User'),
排列(
“Click.created BETWEEN?AND?”=>数组($from,$to),
'Sale.salled BETWEEN?和?'=>数组($from,$to)
),
数组('User.username','Click.unique','Click.clicks','Sale.sales_1','Sale.sales_2')
));
}
好的,我发现$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()
是的,我发现将public$paginate=array()
放在注释之后:)无论如何,不幸的是没有任何更改-仍然只有用户字段可以排序(查询中没有ORDER BY子句)。然后需要调试;)这就是我害怕的:)无论如何,我发现这就是问题所在<代码>$correctAlias
正在为非用户字段获取false
。不幸的是,我不知道该怎么做。这会起作用的-您也可以使用控制器操作中的registered来做同样的事情。很高兴你找到了一个有效的解决方案+1。另外,信任白名单的问题刚刚解决。