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。另外,信任白名单的问题刚刚解决。