我有一个GridView表,我想计算余额,因为在DB中只有借方和贷方。
我在模型中添加了一个新的对象变量balance
和一个保存最后余额的类-var tempBalance
。
在SearchModel中,我有以下几行来计算余额
private function calculateBalance($dataProvider) {
foreach ($dataProvider->models as $model) {
$model->balance = parent::$tempBalance + $model->debit - $model->credit;
parent::$tempBalance = $model->balance;
}
}
这很好用,但是当我在GridView中有超过20个结果时,它会自动生成每20条记录的页面(我想保留这个分页)。问题是,在每个页面上saldo都以0开头,但我想显然仍然是上一页最后一个条目的saldo。
我试图关闭paginatinon进行计算,然后再打开它,但这就是我努力的地方。
我试图在foreach
方法的calculateBalance()
循环之前关闭分页:
$pagination = $dataProvider->getPagination();
$dataProvider->setPagination(false);
然后通过以下代码在循环之后再次打开它:
$dataProvider->setPagination($pagination);
但是这并没有再次打开分页。分页仍然关闭。
有没有办法可以忽略我的计算分页,还是重新打开分页的正确方法?
关闭后如何打开分页?
答案 0 :(得分:0)
$dataProvider->models
,如果您要更改分页设置,则必须调用$dataProvider->prepare(true)
以强制数据提供程序从数据库中重新获取数据。
类似的东西:
// setup $dataProvider
// render GridView
$dataProvider->setPagination(false);
$dataProvider->prepare(true);
$this->calculateBalance($dataProvider);
但是计算模型上的平衡是一个非常糟糕的主意 - 如果有人拥有数百万条记录,那么它将会非常缓慢,最终你会失去内存错误。您应该通过SQL查询计算余额 - 它会更快,并且不会爆炸大数据集。
$balanceQuery = clone $dataProvider->query;
$balanceQuery->select([
'debit' => new Expression('SUM(debit)'),
'credit' => new Expression('SUM(credit)'),
]);
$balanceData = $balanceQuery->asArray()->one();
$balance = $initialBalance + $balanceData['debit'] - $balanceData['credit'];
请注意,过滤网格数据会改变平衡(因为$dataProvider->query
会忽略某些数据)。如果这不是故意的,您应该在应用过滤或使用新查询之前克隆$query
,例如$balanceQuery = MyModel::find()->onlyForUser($userId);
。