Skip to content
Advertisement

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.

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.

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement