I
I
InfoLabs2016-10-21 17:08:25
Yii
InfoLabs, 2016-10-21 17:08:25

How to reduce number of yii2 requests on GridView?

Hello. Faced a problem. There are tables
1) id, name, subname
2) id, user_id, status, message
It is necessary to provide output of custom columns when displaying table 1 in gridview. Each of which will count the number of records in table 2 with different statuses. (1 custom column - status 1, 2 custom column - status 2)
Now I use the relationship every time when fetching the number of records with a certain status. As a result, +1 request to the database for each column.
Question: How can I execute such a query in one go, save it, and use the saved values ​​for subsequent columns?
SQL: select `status`, count(`id`) from `orders` where `user_id`=*ID here in general via relationship* group by `status`
-----
Here is how the
View is implemented now:

<?= GridView::widget([
                'dataProvider' => $dataProvider,
                'columns' => [
                    ['class' => 'yii\grid\SerialColumn'],
                    'id',
                    [
                        'header' => 'Активные заказы',
                        'format' => 'raw',
                        'value' => function($model) {
                            return $model->activeCount;
                        }
                    ],
                    [
                        'header' => 'Ожидают модерации',
                        'format' => 'raw',
                        'value' => function($model) {
                            return $model->moderateCount;
                        }
                    ],
                    ['class' => 'yii\grid\ActionColumn']
                ],
            ]); ?>

Modelka:
class Users extends ActiveRecord
{
    public static function tableName()
    {
        return 'users';
    }

    public function rules()
    {
       /*----*/
    }

    public function attributeLabels()
    {
         /*----*/
    }

    public function getOrders()
    {
        return $this->hasMany(Orders::className(), ['user_id' => 'id']);
    }

    public function getActiveCount()
    {
        return $this->getCount(1);
    }

    public function getModerateCount()
    {
        return $this->getCount(0);
    }

    private function getCount($status)
    {
        return $this->getOrders()->where(['status' => $status])->count();
    }
}

Answer the question

In order to leave comments, you need to log in

2 answer(s)
I
InfoLabs, 2016-10-21
@InfoLabs

Decision:

public function getOrdersAggregation()
    {
        return $this->getOrders()
            ->select(['status', 'count' => 'count(*)'])
            ->groupBy('status')
            ->asArray(true);
    }

    public function getOrdersStatusCount(int $status) : int
    {
        if( empty($this->ordersAggregation) ) {
            return 0;
        }

        $result = ArrayHelper::map($this->ordersAggregation, 'status', 'count');

        if( ! array_key_exists($status, $result) ) {
            return 0;
        }

        return $result[ $status ];
    }

M
Maxim Fedorov, 2016-10-21
@qonand

use joinWith to solve this problem

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question