slifty
slifty

Reputation: 13791

Conditionally building an Eloquent query

The Context

I'm using Laravel's Eloquent as my ORM. I am creating an API endpoint which provides access to Cars which have several attributes (color, make, status).

My endpoint allows clients to filter the return value by any subset of those attributes, if they provide no attributes then I will return everything.

The Question

I want to build a conditional query, which starts from "all" and narrows down based on which parameters have been specified. Here's what I've written:

public function getCars(Request $request)
{
    $results = Cars::all();

    if($request->has('color'))
         $results = $results->where('color', $request->input('color'));

    if($request->has('make'))
         $results = $results->where('make', $request->input('make'));

    if($request->has('status'))
         $results = $results->where('status', $request->input('status'));

    return $results->toJson();
}

If I call this with no parameters the API returns a list of all cars in the database. If, however, I specify (for instance) status of 0 the API returns an empty set, despite the fact that some cars have status of 0.

Am I approaching this incorrectly? Is there something fundamental I'm missing?

Note that if instead I write:

$results = Cars::where('status', 0);
return $results->get();

The list of cars is properly generated

Upvotes: 3

Views: 2940

Answers (2)

lagbox
lagbox

Reputation: 50491

You could try this, for simplicity.

$query = Cars::query(); // no query executed, just give us a builder

$query->where(array_only($request->all(), ['color', 'make', 'status'])); // where can take a key value array to use
// update: only taking the vars you need, never trust incoming data

return $query->get(); // will be converted to Json for you

This only queries the DB for what you need. Yours is returning all results then filtering through them in a collection.

Update: As Joseph stated, there is different functionality between $request->only() and array_only. The functionality of array_only is wanted here.

Upvotes: 3

Marcin Nabiałek
Marcin Nabiałek

Reputation: 111859

You should change your function like this:

public function getCars(Request $request)
{
    $results = Cars::query();

    if($request->has('color'))
         $results = $results->where('color', $request->input('color'));

    if($request->has('make'))
         $results = $results->where('make', $request->input('make'));

    if($request->has('status'))
         $results = $results->where('status', $request->input('status'));

    return $results->get()->toJson();
}

Upvotes: 8

Related Questions