Search code examples
phplaravel-5dynamicquery

Can I chain a variable number of query scopes using Laravel 5


My users need to be able to query the database with up 5 different parameters. I think the best way to handle this is with query scopes. Then just chain together the query scopes. But I cannot figure out how to do this based on an unknown number (0-5) of search parameters.

I have it working with one specific search parameter.

$thirtyDaysAgo = Carbon::now()->subDays(30)->toDateString();
$orders = Order::DateRange($thirtyDaysAgo)->get();
return view('orders/browse', compact('orders'));

Any help would be appreciated.

Edit: More info

Parameters are posted to the page from a form:

$input = Input::all();
dd($input);

yields

array:7 [▼
"_token" => "MX4gVmbON56f9Aa88kgn2Re68GoDrtDeR6phEJ30"
"orderType" => "1"
"orderNumber" => "1"
"timePeriod" => "0"
"orderStatus" => "0"
"sku" => ""
"customer" => "0"
]

Edit: Adding query scopes

public function scopeDateRange($query, $range){
    return $query->where('created_at', '>=', $range);
}

public function scopeOrderNumber($query, $orderNumber){
    return $query->whereOrderNumber($orderNumber);
}

public function scopeCustomer($query, $customer){
    return $query->whereCustomerId($customer);
}

public function scopeStatus($query, $status){
    if($status == 'active'){
        return $query->where('orderStatus_id', '!=', 15)->where('orderStatus_id', '!=', 10);
    }elseif($status == 'complete'){
        return $query->whereOrderStatusId(15);
    }elseif($status == 'cancelled'){
        return $query->whereOrderStatusId(10);
    }
}

Solution

  • By the looks of it, you are going to want to just check to see if your parameters are empty, and if so, you can just return the query and not perform the scope check:

    public function scopeDateRange($query, $range){
        if (!empty($range)) {
            return $query->where('created_at', '>=', $range);
        }
        else {
            return $query;
        }
    }
    

    Then, you can just chain them all together and the scope functions will sort out whether or not to filter the query all by themselves.

    $orders = Order::dateRange($range)->orderNumber($orderNumber)->customer($customer)->status($status)->get();