@InfoLabs

Как сократить кол-во запросов yii2 при GridView?

Здравствуйте. Столкнулся с проблемой. Имеются таблицы
1) id, name, subname
2) id, user_id, status, message
Необходимо при выводе в гридвью таблицы 1 предусмотреть вывод кастомных колонок. Каждая из которых будет считать кол-во записей в таблице 2 с разными статусами. (1 кастомная колонка - status 1, 2кастомная колонка - status 2)

Сейчас я каждый раз использую связь при выборке кол-во записей с определенным статусом. В итоге на каждую колонку +1 запрос в бд.

Вопрос: Как я могу за один заход исполнить такой запрос, сохранить его, и для последующих колонок использовать сохраненные значения?
SQL: select `status`, count(`id`) from `orders` where `user_id`=*ИД тут вообще через связь* group by `status`

-----

Вот как реализовано сейчас
Представление:
<?= 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']
                ],
            ]); ?>


Моделька:
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();
    }
}
  • Вопрос задан
  • 280 просмотров
Решения вопроса 1
@InfoLabs Автор вопроса
Решение:
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 ];
    }
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
qonand
@qonand
Software Engineer
используйте для решения этой задачи joinWith
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы