I'm facing a complex problem in Laravel concerning Eloquent relationships. I'd appreciate any assistance you can provide.
Here's the structure of my tables:
Tables:
albums
: id
, name
photos
: id
, name
layouts
: id
, name
album_photo
: album_id
, photo_id
album_photo_layout
: album_id
, photo_id
, layout_id
, visibility
Relationships:
albums
and photos
with a pivot table album_photo
).albums
, photos
, and layouts
with a pivot table album_photo_layout
).What I'm trying to achieve is to get all albums, with all photos in each album, and all possible layouts for each photo. If a certain layout is not linked with a photo for a specific album, I want it to be added with a default visibility value.
Here is my current approach:
$album->load([
'photos.layouts' => fn($query) => $query->where('album_id', $album->id)
]);
But this doesn't include layouts that haven't been linked with a photo for a specific album. These missing layouts should be included with a default visibility
value.
I've tried to address this using whenLoaded()
in the resource, but without success. It returns null
for missing layouts and doesn't meet my requirements.
Ideally, I want a solution that adheres to the Eloquent ORM principles, without resorting to raw SQL queries.
You might want to change things up a bit.
Album:
- id
- name
- hasMany(AlbumPhoto)
Photo:
- id
- name
- hasMany(AlbumPhoto)
Layout
- id
- name
- hasMany(AlbumPhotoLayout)
AlbumPhoto
- id
- belongsTo(Photo)
- belongsTo(Album)
- hasMany(AlbumPhotoLayout)
AlbumPhotoLayout
- id
- belongsTo(AlbumPhoto)
- belongsTo(Layout)
What you are looking for is Album::with('albumPhoto.albumPhotoLayout');
I find it useful in many cases to model pivots as models. Also, you can find a middle ground by defining Pivot
classes. Actually, AlbumPhoto
and AlbumPhotoLayouts
can extend Pivot
instead of Model
.