Групповая коллекция с помощью created_at и отношения к файлам

#laravel #thephpleague-fractal

#laravel #thephpleague-фрактал

Вопрос:

У меня есть это отношение:

У каждого пользователя есть галерея, а в галерее много файлов.

У двух пользователей может быть галерея с одинаковой датой.

Это выходной ответ JSON:

 User1 {
 galleries: {
  created_at: 23.04.2019.
  files: [
    {
     path: "path/to/file.jpg"
    },
    {
     path: "path/to/file2.jpg"
    },
  ]
 }
},
User2 {
 galleries: {
  created_at: 23.04.2019.
  files: [
    {
     path: "path/to/file3.jpg"
    },
    {
     path: "path/to/file4.jpg"
    },
  ]
 }
}
  

Мне нужно как-то сгруппировать галереи по значению created_at, но сохранить все файлы в одном и том же ответе JSON для сгруппированного объекта galleries. Вот так:

 Users {
 galleries: {
  created_at: 23.04.2019.
  files: [
    {
     path: "path/to/file.jpg"
    },
    {
     path: "path/to/file2.jpg"
    },
    {
     path: "path/to/file3.jpg"
    },
    {
     path: "path/to/file4.jpg"
    },
  ]
 }
},
  

Я пытался использовать ->groupBy('galleries.created_at') , но что я получаю это — первый файл из первой галереи, первый файл из второй галереи

 Users {
 galleries: {
  created_at: 23.04.2019.
  files: [
    {
     path: "path/to/file.jpg"
    },
    {
     path: "path/to/file3.jpg"
    },
  ]
 }
},
  

Комментарии:

1. Можете ли вы показать, как вы создаете свою коллекцию?

2. Я использую фрактальные преобразователи с return $this->collection($user->galleries, new GalleryTransformer()); , если вы имеете в виду, что

3. Вероятно, лучше посмотреть документацию по пакету. Может быть не чисто Laravel вопрос. Я не могу догадаться, что внутри GalleryTransformer 🙂

Ответ №1:

Перед передачей данных во фрактальный преобразователь необходимо получить правильные данные. Ваш желаемый результат выглядит как список File файлов, упорядоченных по Gallery дате. На самом деле это не имеет никакого отношения к Users (если вы не планируете позже охватывать возвращаемые данные). При этом красноречивые отношения здесь не помогут, поскольку мы не имеем дело с отношениями одной модели, и мы можем просто использовать конструктор запросов Laravel и использовать groupBy вспомогательную функцию Collection для организации результатов.

Вам решать, куда поместить этот метод; он может легко перейти в метод контроллера, но если вы планируете ограничить результаты (например, до определенных User значений или для определенных дат, как показано ниже), вы можете включить его в модель.

 // Gallery.php

public static function filesByGalleryDate($date = null) {
    $query = DB::table('gallery')
        ->leftJoin('files', 'galleries.id', '=', 'files.gallery_id')
        ->select('galleries.created_at', 'files.*')
        ->orderBy('galleries.created_at');

    $result = $date == null 
        ? $query->get()
        : $query->where('galleries.created_at', $date)->get();

    return $result->groupBy('created_at')

        // for each date, convert inner stdClasses to arrays
        ->map(function($date) { 
            return $date->map(function($file) { 
                return (array) $file; 
            }); 
        });
}