I have an album that has images. I’m having a problem with doing the search function. I want to search for photos with the following caption. Here’s what I did so far.
Albums table:
| id | album_name | sort | |----|------------|------| | 1 | album_1 | 3 | | 2 | album_2 | 2 | | 3 | album_3 | 1 |
Photos table:
| id | album_id | name | sort | |----|----------|-------|------| | 1 | 1 | name1 | 1 | | 2 | 1 | name2 | 2 | | 3 | 2 | name3 | 3 |
and the following relations on my models:
Photo.php
public function album() { return $this->belongsTo(Album::class); }
Album.php
public function images() { return $this->hasMany(Photo::class, 'album_id', 'id)->orderBy('sort'); }
GalleryController.php
public function index(Request $request) { $photos = Album::has('images')->orderBy('sort')->with('images')->get(); } if (!empty($request->search)) { $photos = Album::whereHas('images', function($query) use ($request) { $query->where('name', 'like', '%' . $request->search . '%'); })->with('images')->get();
The search function works but if I search for a specific image within the album it returns all of the images in that album.
Advertisement
Answer
It’s not very pretty, but this is basically what you want.
I’ve commented the code to explain it.
if (!empty($request->search)) { $queryString = '%' . $request->search . '%'; $queryClosure = function ($query) use ($queryString) { $query->where('name', 'LIKE', $queryString); }; // Get only albums that have images that match the query string. // This will filter the albums, not the images. $photos = Album::whereHas('images', $queryClosure) // Now filter the images of those albums. ->with(['images' => $queryClosure]) // Return the collection. ->get(); }
Edit:
I have updated the answer to use Tim Lewis’s suggestion from the comments.
Since the closure is repeated for both steps, we can store it in a variable to keep the code DRY.