2

User モデルで find type メソッドをカスタマイズしました。

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;
}

今、他のコントローラー (という名前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フィールド (通常はユーザー フィールド) でしか注文できないことです。許可されたフィールドを 3 番目のパラメーターで指定しController::paginate()ても機能しません。Paginator Helperリンクは適切な URL (例: ) を生成し/admin/reports/index/sort:Click.clicks/direction:ascますが、SQL クエリに ORDER BY 部分が表示されません。たとえば、フィールドが空である場合は、入力し debug($query)ました。_findStats()Click.clicks$query['order']

4

2 に答える 2

1

わかりました、$query は「並べ替え」キーと「方向」キーも受け取ることがわかりました。だから、ここに解決策があります:

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()

于 2013-07-16T12:43:04.787 に答える
0

存在しないフィールドによる並べ替え

質問のコードから - あなたはすでに正しいことをしているようです。

ページネーター コンポーネントは、並べ替え順序が要求からのものである場合、それを検証します。

$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')
    ));
}
于 2013-07-16T08:32:47.600 に答える