yiisoft / yii2

Yii 2: The Fast, Secure and Professional PHP Framework

Home Page:http://www.yiiframework.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Bug fix #20055 causes bad result for pagination using for example gridview

procin opened this issue · comments

What steps will reproduce the problem?

When creating the dataprovider, for example:
$provider = new ActiveDataProvider([
'query' => ...,
'pagination' => [...]
]);

Setting the 'pagination' calls the setPagination() function, which now directly calls the getTotalCount() function, which calls the prepareTotalCount() function.
Now the value for $_totalCount will be queried from the database.

When using a GridView with a SearchModel, the search parameters for the query are loaded in a later stage.
The search parameters can cause for a different number of rows to be returned.

The prepareTotalCount() is not called again, because $_totalCount is already set.

The pagination bar now works with a completely wrong count value. (for example, displays more pages than there actually are)

Calling prepareTotalCount() again is not a solution, the count on a big table can be very expensive.

Additional info

Q A
Yii version 2.0.50

#20055 @lav45 would you please take a look?

@samdark it seems since 2.0.50 the active data provider is broken when using pagination and/or sort params:

yii\base\InvalidConfigException: The "query" property must be an instance of a class that implements the QueryInterface e.g. yii\db\Query or its subclasses. in /var/www/html/vendor/yiisoft/yii2/data/ActiveDataProvider.php:164
Stack trace:
#0 /var/www/html/vendor/yiisoft/yii2/data/BaseDataProvider.php(171): yii\data\ActiveDataProvider->prepareTotalCount()
#1 /var/www/html/vendor/yiisoft/yii2/data/BaseDataProvider.php(222): yii\data\BaseDataProvider->getTotalCount()
#2 /var/www/html/vendor/yiisoft/yii2/base/Component.php(180): yii\data\BaseDataProvider->setPagination()
#3 /var/www/html/vendor/yiisoft/yii2/BaseYii.php(557): yii\base\Component->__set()
#4 /var/www/html/vendor/yiisoft/yii2/base/BaseObject.php(107): yii\BaseYii::configure()

this code breaks with the above stack trace in version 2.0.50

return new ActiveDataProvider([
            'pagination' => [
                'defaultPageSize' => 75,
            ],
            'query' => $query
                ->select([SchemaRow::tableName().'.id', 'title', 'subtitle', 'is_visible'])
                ->byLikeTitle($model->query)
                ->isNotTrashed()
                ->andFilterWhere([SchemaRow::tableName().'.id' => $model->ids])
                ->bySchemaId($id),
            'sort' => [
                'defaultOrder' => [
                    'title' => SORT_ASC,
                ],
            ],
        ]);

removing the sort/and or pagination definition and it works again. We had to downgrad to 2.0.49 in order to get the app working.

change the code to:

return new ActiveDataProvider([
            'query' => $query
                ->select([SchemaRow::tableName().'.id', 'title', 'subtitle', 'is_visible'])
                ->byLikeTitle($model->query)
                ->isNotTrashed()
                ->andFilterWhere([SchemaRow::tableName().'.id' => $model->ids])
                ->bySchemaId($id),
        ]);

for testing, and it works also in 2.0.50

php 8.3.4

@samdark not sure its related to be honest. but i also have problems with the active data provider with latest version. Let me know if i should create a fresh issue.

commented

@nadar fixed in to the PR #20176

commented

Workaround is to make sure the configuration array contains query before pagination. That way query is set before pagination is set.