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);
}
}
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();
Yes you can, just loop the user input fields, for example:
// You have this right now, so until get is called you can chain $thirtyDaysAgo = Carbon::now()->subDays(30)->toDateString();
// Remove the get call
$order = Order::DateRange($thirtyDaysAgo); // Or use Order::query()
// Loop other fields (exclude fields which are not required in query)
foreach(Request::except(['_token', 'other_field_name']) as $field => $value)
{
// Make sure $field (form fields) match with database filed names
$order->where($field, $value);
}
$result = $order->get(); // Run the query and get the result
This is an idea and you may need to tweak to make it fit according to your need. Try it by yourelf or post most relevant information. This is not using scopeMethods
but you can do it to get what you are up to.