CakePHP将数组传递给paginate() - 新模型

时间:2013-06-20 09:11:45

标签: cakephp pagination

您好我已经完成了一个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++;
}

我现在需要将它传递给paginate,但我读here你不能这样做,我必须创建另一个模型才能在这个特定的find上使用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

关于在一个表中使用2个模型的文档中似乎没有太多内容

1 个答案:

答案 0 :(得分: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”添加到数据库即可删除问题,并在更改时重新计算。这意味着从费用索赔模型中读取时绝对没有额外的逻辑。

使用自定义查找类型

如果您不想重新计算所有查找的总数 - 您可以创建custom find type

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

然后use it in your paginate call

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

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

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

这样,只有索引方法才会触发调用以添加总计。