【问题标题】:Yii2 GridView pagination with only next and prev links and no TotalCountYii2 GridView 分页只有下一个和上一个链接,没有 TotalCount
【发布时间】:2023-03-24 14:31:01
【问题描述】:

有一个包含数百万行的巨大数据库表,它需要在分页器中只有 prev 和 next 链接的 GridView 中输出。

我不想在此类表上使用“select count(*)”,因此没有 TotalCount。另外我想防止用户设置巨大的偏移量并降低 MySQL 的性能。

谁能帮帮我?

【问题讨论】:

  • Accepted answer有错误:应该有 $page = $pagination->getPage(true);而不是 $page = $pagination->getPage(true) + 1;否则,您总是会跳过结果的第一页,因为生成的查询包含 $page == 1 的“offset 20”。

标签: php gridview pagination yii2


【解决方案1】:

当你创建你的 dataprovider 时,确保将 totalCount 指定为一个数字,例如 0,这将阻止 Yii 运行 count(*) 查询。

然后你应该为 yii\widgets\Linkpager 创建一个替换类,它只生成你想要显示的链接。

最后,将寻呼机附加到 GridView。

<?php GridView::widget([
'dataProvider'=>$dataProvider,
'pager' => [
   'class' => 'path\to\my\custom\Pager\'
 ]
 'columns' => 
         ....
]; ?>

【讨论】:

    【解决方案2】:

    我已经等了几天,以确保我没有遗漏一些明显的解决方案,但现在需要自己硬编码。我发现最快的方法是扩展 DataProvider 并重写方法:prepareTotalCount()prepareModels()

    namespace common;
    use yii\data\ActiveDataProvider;
    use yii\base\InvalidConfigException;
    use yii\db\QueryInterface;
    
    class BigActiveDataProvider extends ActiveDataProvider
    {
        protected function prepareTotalCount() {
            return 0;
        }
    
        protected function prepareModels()
        {
            if (!$this->query instanceof QueryInterface) {
                throw new InvalidConfigException('The "query" property must be an instance of a class that implements the QueryInterface e.g. yii\db\Query or its subclasses.');
            }
            $query = clone $this->query;
    
            if (($pagination = $this->getPagination()) !== false) {
                $pagination->validatePage = false;
                $page = $pagination->getPage(true) + 1;
                $offset = $page*$pagination->getPageSize();
    
                $query->limit($pagination->getLimit() + 1)->offset($offset);
            }
            if (($sort = $this->getSort()) !== false) {
                $query->addOrderBy($sort->getOrders());
            }
    
            $res = $query->all($this->db);
    
            if (($pagination = $this->getPagination()) !== false) {
                $pagination->totalCount = ($page)*$pagination->getPageSize();
                if (count($res) > $pagination->getPageSize()) {
                    unset($res[count($res)-1]);
                    $pagination->totalCount++;
                }
            }
    
            return $res;
        }
    }
    

    我不认为这是最好的解决方案,但它可以按计划工作,并且不会限制ActiveDataProvider 的功能。它只是确保 count(*) 查询不会被执行,并且不需要设置totalCount

    【讨论】:

    • 这是一个很好的答案,但并不完美,因为它实际上将第二页显示为第一页(IE 它将偏移量设置为 11)。要解决此问题,您无需在顶部将页面设置为 + 1,因此像这样 $query->limit($pagination->getLimit() + 1)->offset($offset);在底部,您确实需要设置 page + 1 $pagination->totalCount = ($page + 1)*$pagination->getPageSize();
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 2013-08-26
    • 2014-09-26
    相关资源
    最近更新 更多