Reputation: 125
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.
Upvotes: 1
Views: 177
Reputation: 3968
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.
Upvotes: 2