我正在使用 SqlDataProvider在 Yii2
中,这是一般示例:
$count = Yii::$app->db->createCommand('
SELECT COUNT(*) FROM user WHERE status=:status
', [':status' => 1])->queryScalar();
$dataProvider = new SqlDataProvider([
'sql' => 'SELECT * FROM user WHERE status=:status',
'params' => [':status' => 1],
'totalCount' => $count,
'sort' => [
'attributes' => [
'age',
'name' => [
'asc' => ['first_name' => SORT_ASC, 'last_name' => SORT_ASC],
'desc' => ['first_name' => SORT_DESC, 'last_name' => SORT_DESC],
'default' => SORT_DESC,
'label' => 'Name',
],
],
],
'pagination' => [
'pageSize' => 20,
],
]);
您可以看到,在获取实际数据结果的 SqlDataProvider
内的实际查询之前,它在查询中执行了 COUNT
。
但是,我更愿意使用 SLC_CALC_FOUND_ROWS
,因为此数字是一种更可靠的方法,可以获取与 DataProvider 内查询返回的实际行数相匹配的正确数字,因为匹配的行可能是可能会在 COUNT
查询和 SqlDataProvider
查询之间添加或删除,因此我需要更可靠的东西。
我可以锁定表,但我不认为这是明智的想法,因此我需要使用 SQL_CALC_FOUND_ROWS 来获取正确的金额,但我不确定如何使用数据提供者。
这将是执行我想要的操作的代码:
$sql = $this->db->createCommand("SELECT FOUND_ROWS()");
$count = $sql->queryScalar();
$dataProvider->totalCount = $count;
...但这不起作用,所以正如我所说,我不确定如何实现代码以与 SqlDataProvider
一起使用。
最佳答案
据我了解,SqlDataProvider
的作用方式如下:
- 如果没有设置分页,数据提供者将查询数据库,然后
count()
结果生成的模型。 这就是您想要的行为。 - 如果设置了分页,它将使用
$totalCount
提供的值,或者如果$totalCount == NULL
将返回SqlDataProvider::的值prepareTotalCount()
设置为返回0
。 这不是您想要的行为。
我认为在查询中利用分页并在没有两次查询的情况下获得准确的总数是不可能的。毕竟分页的重点是不必处理所有返回的元素。
我看到两种可能性。
您可以删除分页并单独处理它。这只是 如果你知道你的返回集将是相对可行的 小的。在大多数实际情况下,这不是一个选择。
这导致我们必须运行两个查询。如果你没问题 两个查询的想法,您认为有必要将它们执行为 尽可能靠近,以下是您如何继续获取 最佳结果:
- 将
SqlDataProvider
扩展为一个新类。我们将其命名为CustomSqlDataProvider
- 设置新的
public $totalCountCommand
属性。 - 编写
prepareTotalCount()
方法来覆盖默认行为
大致如下:
protected function prepareTotalCount()
{
return $this->totalCountCommand->queryScalar();
}
然后您可以简单地按照以下方式创建数据提供程序:
$countCommand = Yii::$app->db->createCommand('
SELECT COUNT(*) FROM user WHERE status=:status
', [':status' => 1]);
$dataProvider = new CustomSqlDataProvider([
'sql' => 'SELECT * FROM user WHERE status=:status',
'params' => [':status' => 1],
'totalCountCommand' => $countCommand,
'sort' => [
'attributes' => [
'age',
'name' => [
'asc' => ['first_name' => SORT_ASC, 'last_name' => SORT_ASC],
'desc' => ['first_name' => SORT_DESC, 'last_name' => SORT_DESC],
'default' => SORT_DESC,
'label' => 'Name',
],
],
],
'pagination' => [
'pageSize' => 20,
],
]);
这应该做的是,当数据提供程序获取结果集时运行计数查询,而不是在数据提供程序设置时完成计数时最初执行的查询>(技术上什至在设置之前就已经很好了)
PS:我没有测试过这段代码,只是阅读了yii2代码。然而,它应该要么进行一些小的调整,要么让你走上正确的道路。如果您需要任何额外信息,请告诉我。
关于php - 在 Yii2 的 SqlDataProvider 中使用 SQL_CALC_FOUND_ROWS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29668164/