0

I've got an Album model. An Album can have many Event and many Picture but an Event belongs to one Album and one Picture belongs to one Album too.

I'm trying to make a list of events. In each event, I would like to display album's title and 3 random pictures from this album.

I think I have to use Eager Loading to do so but I'm a little bit confused. Currently I can have a list of albums and take 3 random pictures from them like this:

$albums = Album::with(array('pictures' => function($query) {
    $query->orderByRaw("RAND()")->take(2);
}))->get();

foreach ($albums as $album) {

    echo $album->title;

    foreach ($album->pictures as $picture) {

        echo $picture->filename;

    }

}

This is working but I have to start from events instead of albums. I don't know how to make all these relations work together. Event -> Album -> Pictures and display them into a view.

Flobesst
  • 1,281
  • 1
  • 16
  • 26
  • Have you tried something like $Event::with(['Album' => function($q) { $q->with('Picture')->orderByRaw('RAND()')->take(2); }]); – cubiclewar Oct 03 '14 at 00:52
  • You can't use `take` on eager loaded query to load 2 pictures per album, it will limit all pictures to 2. Read this: http://softonsofa.com/tweaking-eloquent-relations-how-to-get-n-related-models-per-parent/ – Jarek Tkaczyk Oct 03 '14 at 07:21
  • @cubiclewar unfortunately I get `Call to undefined method Illuminate\Events\Dispatcher::with()` @JarekTkaczyk wow, it seems to be very painful ! All this code just to query on some relations ? Are you sure there's no simple way to do this ? – Flobesst Oct 03 '14 at 15:05
  • @Tkaczyk ah of course same behavior as limitTo() – cubiclewar Oct 04 '14 at 00:51

1 Answers1

1

Then you need a one-to-many relationship and you need to create relationship methods for both sides, for example:

In Event model:

public function album()
{
    return $this->belongsTo('Album', 'album_id');
}

In Album model:

public function events()
{
    return $this->hasMany('Event', 'album_id');
}

public function pictures()
{
    return $this->hasMany('Picture', 'album_id');
}

So now you are able to start with Event, for example:

$events = Event::with('album.pictures')->get(); // or paginate(10), 10 per page
The Alpha
  • 143,660
  • 29
  • 287
  • 307
  • Thanks for your answer, I updated my code to work with your solution. But I still have a problem: when I do `$query->orderByRaw("RAND()")->take(2);` to show only 2 album pictures per event (like in my 1st post), I only get 2 pictures for ALL events. Only the last event in list will have it's 2 pictures, not the other ones... – Flobesst Oct 03 '14 at 14:56
  • Sorry! i didn't get what you asked for now, what it does now ? – The Alpha Oct 03 '14 at 18:36
  • Let's say that I have 3 events to display and I want to show 2 pictures per event. If I use `->take(2)` on the query like I said above, only one event will show the 2 pictures, the other ones are empty. – Flobesst Oct 04 '14 at 02:23