Jeano
Jeano

Reputation: 125

Search query function on Laravel

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

Answers (1)

BritishWerewolf
BritishWerewolf

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

Related Questions