@Vermut756

Как в PHP, желательно именно совместимо с Yii2 ActiveDataProvider, выбрать данные из таблицы, чтобы в JSON группировать их по дате?

Вот так выглядит запрос без "группировки":
$query = $query->orderBy(['dt' => SORT_DESC, 'id' => SORT_DESC]);
return new ActiveDataProvider([
          'query' => $query,
          'pagination' => [
              ...
          ]
      ]);


Далее там RestController, вот что выводит в итоге:
{
"items": [
  {
    "id": "5",
    "dt": "2017-01-10 07:56",
    ...
  },
  {
    "id": "4",
    "dt": "2017-01-10 07:55",
    ...
  },
  {
    "id": "3",
    "dt": "2017-01-09 13:52",
    ...
  },
  ...
]
}


Все бы ничего, но мне нужно еще и группировать данные в JSON по дате. То есть вот так:
{
"items": [
  "2017-01-10": [
    {
      "id": "5",
      "dt": "2017-01-10 07:56",
      ...
    },
    {
      "id": "4",
      "dt": "2017-01-10 07:55",
      ...
    }
  ],
  "2017-01-09": [
    {
      "id": "3",
      "dt": "2017-01-09 13:52",
      ...
    }
  ]
  ...
]
}

Это потом понадобится во фронт-енде.

И вот здесь проблемы.
Сперва в MySQL есть GROUP BY, есть и метод для него в Yii2 ActiveQuery, но, как я понял, это совсем не то, то есть он не возвращает такой вложенный массив, а делает что-то вообще другое.
Тогда я просто делаю так:
$query = $query->orderBy(['dt' => SORT_DESC, 'id' => SORT_DESC]);
$rawArr = $query->all();

А затем в цикле вручную формирую новый объект и в нем группирую все как надо
Но что дальше?
Ведь подсунуть уже готовый объект в ActiveDataProvider я не могу.
Можно вообще избавиться от ActiveDataProvider и возвращать напрямую объект, но мне еще пагинация нужна, получается ее я тоже должен сам реализовать, что уже достаточно неудобно, долго и чревато SQL-уязвимостями.

Как можно решить проблему - сделать такой объект, при этом сохранив поддержку ActiveDataProvider для реализации пагинации и др.?
  • Вопрос задан
  • 366 просмотров
Пригласить эксперта
Ответы на вопрос 3
@Arik
Это потом понадобится во фронт-енде.

Может на "фронт-енде" и надо собирать в такой массив? Зачем на серверной стороне собирать? или тоже используете?
Ответ написан
Комментировать
sidan
@sidan
php-developer
Через group by желаемый результат не получить.
Обычно это делается уже после получения всех интересующих записей, что-то типа:
$byDate = ArrayHelper::map($dataProvider->getModels(), 'dt', function($data) { return $data; });
Ответ написан
Комментировать
qonand
@qonand
Software Engineer
В самом простом варианте можно сделать например так:
$query = $query->orderBy(['dt' => SORT_DESC, 'id' => SORT_DESC]);
$dataProvider  = new ActiveDataProvider([
    'query' => $query,
    'pagination' => [
    .....
    ]
]);
$dataProvider->models = \yii\helpers\ArrayHelper::index($dataProvider->models, null, 'dt');


Но правильнее будет если Вы реализуйте свой дата провайдер наследуемый от текущего и возвращающий результат в нужном виде.
Ответ написан
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы