2

I have this relation:

Each user has gallery and gallery hasMany files.

Two users can have a gallery of the same date.

This is the output JSON response:

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"
    },
  ]
 }
}

I need somehow to group galleries by created_at value, but to keep all files in same JSON response, for the groupped galleries object. Like this:

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"
    },
  ]
 }
},

I tried to use ->groupBy('galleries.created_at'), but that I get this - first file from the first gallery, first file from the second gallery

Users {
 galleries: {
  created_at: 23.04.2019.
  files: [
    {
     path: "path/to/file.jpg"
    },
    {
     path: "path/to/file3.jpg"
    },
  ]
 }
},
Erich
  • 2,408
  • 18
  • 40
Zeljko
  • 61
  • 3
  • Can you show, how do you build your Collection? – Tarasovych Apr 23 '19 at 10:10
  • I use fractal transformers with `return $this->collection($user->galleries, new GalleryTransformer());` if you mean that – Zeljko Apr 23 '19 at 10:22
  • Probably better to look at the package documentation. Might be not pure Laravel question. I can't guess what's inside `GalleryTransformer` :) – Tarasovych Apr 23 '19 at 10:26

1 Answers1

0

Before passing data into a Fractal Transformer, it's a matter of getting the right data. Your desired output looks to be a listing of Files organized by the Gallery date. It doesn't really have anything to do with Users (unless you plan to later scope the returned data). That being said, Eloquent relationships won't really help here since we're not dealing with a single model's relationships, and we can just use the Laravel query builder and use the groupBy Collection helper function to organize the results.

It's up to you where to put this method; it could easily go into a controller method, but if you are planning on scoping the results (e.g. to certain Users, or for certain dates as below), you might have it live in the model.

// 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; 
            }); 
        });
}
Erich
  • 2,408
  • 18
  • 40