Group collection by created_at and file relation

145 Views Asked by At

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

There are 1 best solutions below

0
On

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; 
            }); 
        });
}