user794846
user794846

Reputation: 1931

Filtering Laravel resource collections is there a better way

I am experimenting with creating a Restful API in Laravel and I am making use of the resources feature designed for API output. I have created the following models: Book, Author and Category. I also created a resource for each of these models.

There is a one to many relationship between author and book and a many to many between category and book which has a pivot table.

I can return a collection of all books easily with the following:

return BookResource::collection(Book::with(['author', 'categories'])->paginate(10));

But I want to easily filter by author and category so I have implemented it in the following way inside my controller:

public function index(request $request)
{
    //if no filer params are passed in return all books with author and categories
    if (!$request->has('author') && !$request->has('category')) {
        return BookResource::collection(Book::with(['author', 'categories'])->paginate(10));
    }

    //author param is passed in
    if($request->has('author') && !$request->has('category')){
        $authorName = $request->author;
        return BookResource::collection(Book::whereHas('author', function ($query) use ($authorName) {
            $query->where('name', $authorName);
        })->get());
    }

    //category param is passed in
    if(!$request->has('author') && $request->has('category')){
        $categoryName = $request->category;
        return BookResource::collection(Book::whereHas('categories', function ($query) use ($categoryName) {
            $query->where('name', $categoryName);
        })->get());
    }
}

Is there a better more efficient way of returning the BookResource collection filtered by author and category?

Upvotes: 1

Views: 1439

Answers (1)

Saibal Roy
Saibal Roy

Reputation: 431

Please try to implement this way. Hope this helps. Thanks.

public function index(){
$author = request ('author', null);
$category = request ('category', null);

$books = Book::with(['author', 'categories'])->when($author, function ($query) use ($author) {
 return $query->whereHas('author', function ($query) use ($author){
  $query->where('name', $author);
});
})->when($category, function ($query) use ($category) {
return $query->whereHas('categories', function ($query) use ($category) {
   $query->where('name', $category);
   });
})->paginate(10);
return BookResource::collection($books);
}

Upvotes: 1

Related Questions