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

526
21 января 2017, 14:02

Вот так выглядит запрос без "группировки":

$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 для реализации пагинации и др.?

Answer 1

Пагинацию реализовать совсем не долго, в Вашем случае будет примерно так:

$query = $query->orderBy(['dt' => SORT_DESC, 'id' => SORT_DESC]);
$countQuery = clone $query;
$pages = new Pagination(['totalCount' => $countQuery->count()]);
$rawArr = $query->offset($pages->offset)
              ->limit($pages->limit)
              ->all();

Далее обрабатываете массив так как вам надо и отдаёте клиенту. Подробнее про пагинацию в Yii2

А вообще лучше наверное изменить фронтенд и научить его самому группировать стандартный ответ от ActiveDataProvider, отсортированный по дате(как вы изначально делали).

READ ALSO
Как получить id всех авторов блога Wordpress

Как получить id всех авторов блога Wordpress

Я пишу виджет в котором пользователь сможет в radio выбрать автора и в виджете выведется аватар админа и описание

305
soap xml генерация

soap xml генерация

Как правильно сгенерировать правильно такой xml для soap

328
Functions … is deprecated

Functions … is deprecated

Установил php, phpmyadmin и mysqslПри подключении к БД через phpmyadmin вылезает куча сообщений

371