php - 在 Yii2 的 SqlDataProvider 中使用 SQL_CALC_FOUND_ROWS

标签 php mysql yii yii2

我正在使用 SqlDataProviderYii2 中,这是一般示例:

$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/

相关文章:

PHP获取数组数组中键的最小值

php - 将 MySQL 数据导出为 CSV,支持泰语

yii - 无法通过 yii 中的 clientScript->registerScript 注册普通函数

php - 如何创建仅显示特定 id 数据的 View 页面?我正在使用 Yii 框架

php - 将 PHP 生成的 JSON 保存到文本文件

php - 如何定义一个可以根据MySQL表中的数字获取数据的循环

php 使用 cronjob 执行时不会创建文件

php - 尝试返回此查询的结果?

php - 在mysql中创建表约束

php - Apache 的 x-sendfile 替代方案,用于下载带有恢复支持的大文件