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

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?

  • 写回答

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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?