1

こんにちは、find() を実行し、結果の一部に新しいフィールドを追加しました。

$approved = $this->ExpenseClaim->find('all', array('conditions'=> array('ExpenseClaim.claim_status_id' => '3')));
$i = 0;
foreach ($approved as $ap) {
    $approved[$i]['ExpenseClaim']['claimTotal'] = $this->ExpenseClaim->expenseClaimTotal($approved[$i]['ExpenseClaim']['id']);
    $i++;
}

これをページネーションに渡す必要がありますが、これを行うことはできず、この特定の検索でのみ afterFind() メソッドを使用する別のモデルを作成する必要があることをここで読みました。

だから私は呼ばれる新しいモデルを作成しExpenseClaimTotal、UseTableをに設定しました

public $useTable = 'expense_claims';

次に、新しいモデルの afterFind() メソッドで簡単なデバッグを行いました。

public function afterFind($results, $primary = false) {
    debug($results);
    //return $results;
}

しかし、pagesController でこの新しいモデルに対して検索を実行しようとすると、失敗します。

$this->loadModel('ExpenseClaimTotal');

$approved = $this->ExpenseClaimTotal->find('all', array('conditions'=> array('ExpenseClaim.claim_status_id' => '3')));

これは私が得るエラーです:

Database Error
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'ExpenseClaim.claim_status_id' in 'where clause'

SQL Query: SELECT `ExpenseClaimTotal`.`id`, `ExpenseClaimTotal`.`user_id`, `ExpenseClaimTotal`.`claim_status_id`, `ExpenseClaimTotal`.`created`, `ExpenseClaimTotal`.`modified`, `ExpenseClaimTotal`.`approved`, `ExpenseClaimTotal`.`approved_by`, `ExpenseClaimTotal`.`declined_by`, `ExpenseClaimTotal`.`date_submitted` FROM `expenses`.`expense_claims` AS `ExpenseClaimTotal` WHERE `ExpenseClaim`.`claim_status_id` = 3

1つのテーブルに2つのモデルを使用することについて、ドキュメントにはあまりないようです

4

1 に答える 1

2

配列を改ページしたくない

すでに検索を実行しています。検索を実行してから、結果の配列を改ページするのは賢明ではありません。

モデル データを直接ページ付けし、プロセスに合計値を挿入するだけです。そのため、元の「結果の一部に新しいフィールドを追加する」ロジックをモデルに配置すると、次のようになります。

class ExpenseClaim extends AppModel {

    public function afterFind($results, $primary = false) {

        foreach ($results as &$ap) {
            if (isset($ap['ExpenseClaim']['id'])) {
                $ap['ExpenseClaim']['claimTotal'] = $this->expenseClaimTotal($ap['ExpenseClaim']['id']);
            }
        }

        return $results;
    }
}

コントローラーのコードは次のようになります。

public function index() {

    $conditions = array('ExpenseClaim.claim_status_id' => '3');
    $data = $this->paginate($conditions);

    $this->set('data', $data);
}

そして、コードはシンプルで「ただ動く」だけです。

機能強化

上記は目的の結果を達成するための最も簡単な方法ですが、いくつかの欠点があります。つまり、ほぼすべての検索で total メソッドを呼び出すことになります。

あなたが何をしているかに応じて、たとえば次のことが必要になる場合があります。

合計をキャッシュする

必要に応じて、フィールド「claim_total」をデータベースに追加するだけで問題を解決し、変更されるたびに再計算できます。これは、経費請求モデルから読み取る際に余分なロジックがまったくないことを意味します。

カスタム検索タイプを使用する

すべての検索結果の合計を再計算したくない場合は、カスタム検索タイプを作成できます

class ExpenseClaim extends AppModel {

    public $findMethods = array('allWithTotals' =>  true);

    protected function _findAllWithTotals($state, $query, $results = array()) {
        if ($state === 'before') {
            return $query;
        }

        foreach ($results as &$ap) {
            $ap['ExpenseClaim']['claimTotal'] = $this->expenseClaimTotal($ap['ExpenseClaim']['id']);
        }

        return $results;
    }

そして、それをページネーション呼び出しで使用します:

public function index() {
    $this->paginate['findType'] = 'allWithTotals'; # <-

    $conditions = array('ExpenseClaim.claim_status_id' => '3');
    $data = $this->paginate($conditions);

    $this->set('data', $data);
}

このように、 index メソッドのみが合計を追加する呼び出しをトリガーします。

于 2013-06-20T10:21:20.783 に答える