dongtu1789
2015-05-25 16:53
浏览 117
已采纳

Yii2 GridView分页只有next和prev链接,没有TotalCount

There is a huge DB table with millions of rows and it needs to be outputed in a GridView with only prev and next links in the paginator.

I don't want to use 'select count(*)' on such tables, so there's no TotalCount. Also I want to prevent users from setting huge offset and degrade MySQL performance.

Can anyone help me?

图片转代码服务由CSDN问答提供 功能建议

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

我不想在这些表上使用'select count(*)',所以没有TotalCount。 另外,我想阻止用户设置巨大的偏移并降低MySQL的性能。

任何人都可以帮助我吗?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • dqknycyt92288 2015-06-01 21:10
    已采纳

    I've waited several days to make sure I wasn't missing some obvious solution, but now need to hardcode it on my own. The quickest way I've found is to extend DataProvider and rewrite methods: 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;
        }
    }
    

    I don't think that this is the best solution, but it works as planned and it doesn't limit ActiveDataProvider capabilities. It only makes sure that count(*) query won't be executed and there is no need to set totalCount.

    点赞 打赏 评论
  • duanhong4274 2015-05-29 16:24

    When you create your dataprovider, make sure to specify the totalCount to a number, such as 0, which will prevent Yii from running a count(*) query.

    You should then create a replacement class for yii\widgets\Linkpager that generates only the links you want to appear.

    Finally, attach your pager to your GridView.

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

相关推荐 更多相似问题