I have a function that is supposed to use a combination of filters set by the user to fetch information from a table (or no filters at all).
Keep in mind I'm not trying to override filters here, the query should dynamically add or remove filters depending on the ones set client-side by the user.
The filters work well individually, but when setting multiple of them, the query doesn't fetch the correct data at all. I'm still unable to figure out what the criteria for the incorrect data being fetched is.
The only filters that seem to work in combination with others are date_from and date_to.
This is the function:
public function getReport(Request $request)
{
// Convertir fechas a formato correcto
$request->date_from = date('Y-m-d', strtotime(str_replace('-', '/', $request->date_from)));
$request->date_to = date('Y-m-d', strtotime(str_replace('-', '/', $request->date_to)));
$query = Ticket::all();
$query->when(isset($request->date_from), function ($q) use ($request) {
return $q->where('date_created', '>=', $request->date_from);
});
$query->when(isset($request->date_to), function ($q) use ($request) {
return $q->where('date_created', '<=', $request->date_to);
});
$query->when(isset($request->user), function ($q) use ($request) {
return $q->where('user', $request->user);
});
$query->when(isset($request->paid), function ($q) use ($request) {
if ($request->paid === true) {
return $q->whereNotNull('paid');
} else {
return $q->whereNull('paid');
}
});
$query->when(isset($request->informed), function ($q) use ($request) {
return $q->where('informed', $request->informed);
});
$query->when(isset($request->endorsement), function ($q) use ($request) {
if ($request->endorsement === true) {
$query->where('policy', '<', 1);
} else {
$query->where('policy', '>', 1);
}
});
$query->when(isset($request->duplicate), function ($q) use ($request) {
return $q->where('duplicate', $request->duplicate);
});
$query->when(isset($request->active), function ($q) use ($request) {
return $q->where('active', $request->active);
});
return response()->json($query, $this->success_status);
}
I've tested the $request payload multiple times and there's no issues with the information coming client-side.
What am I doing wrong?
You can try given solution for you problem.
$query = Ticket::all();
if ($request->filled('user')) {
$user = $request->get('user');
$query->where(function ($query) use ($user) {
$query->where('user', $user);
});
}
Note: if it is working perfect then you can add all request parameter according.
First note:
$query = Ticket::all();
In this case $query is not Eloquent query but Laravel Collection.
Another note:
$request is not regular php object with properties, so you have to use ->has(), ->filled() instead of empty() or isset()
Your ->data_to and ->data_from are working, cause you have overwritten those values in the beginning, so they become regular object properties.
Also, I would simplify some parts of your code:
$query->when(isset($request->duplicate), function ($q) use ($request) {
return $q->where('duplicate', $request->duplicate);
});
I would use this construction instead to save some lines:
$query->where('duplicate', $request->get('duplicate', false));
Second param of ->get is default value. If it is not present in request you will get false anyway. So you don't have to care about param existence.
You can apply same logic to all other filters as well.
PS: I don't know your requirements, but this part seems suspicious to me:
$query->when(isset($request->endorsement), function ($q) use ($request) {
if ($request->endorsement === true) {
$query->where('policy', '<', 1);
} else {
$query->where('policy', '>', 1);
}
});
This code will never give 'policy' === 1;
Related
I am stuck in a problem that i want to get filter data in laravel or mysql
which later i will convert into laravel and that is i want to filter values from range slider
of warrenty
which is actually between 80 and 150 (selected by user)
and in database (mysql) i have just minimum value is 80
and maximum value is 200
but by using the following code it only returns maximum value of the given minimum value
$product = product::join('tire_brands', 'product.brand', '=', 'tire_brands.id')
->join('speedrating','product.speedrating','=','speedrating.id')
->where($whereData)
->when(!empty($category), function ($query) use ($category) {
return $query->whereIn('itemtype', $category);
})
->when(!empty($speedrating), function ($query) use ($speedrating) {
return $query->whereIn('speedrating', $speedrating);
})
->when(!empty($tirebrands), function ($query) use ($tirebrands) {
return $query->whereIn('brand', $tirebrands);
})
->when(!empty($minwarrenty) && !empty($maxwarrenty), function ($query) use ($minwarrenty,$maxwarrenty) {
return $query->whereBetween('warrenty', [$minwarrenty, $maxwarrenty]);
})
->when(!empty($minimum_load) && !empty($maximum_load), function ($query) use ($minimum_load,$maximum_load) {
return $query->whereBetween('maxload', [$minimum_load, $maximum_load]);
})
->when(!empty($curroff), function ($query) use ($curroff) {
return $query->whereIn('curr_offerid', $curroff);;
})
->when(!empty($sidewal), function ($query) use ($sidewal) {
return $query->whereIn('sidewall_id', $sidewal);;
})
->when(!empty($tyrtyp), function ($query) use ($tyrtyp) {
return $query->whereIn('tyretype_id', $tyrtyp);;
})
->get(['product.id','product.name as pronam',
'tire_brands.name as brand', 'sku','slug','warrenty','speedrating','itemtype',
'product.image','product.video','speedrating.name as speedrating','touring']);
return $product;
what am i doing wrong?
I am trying to create filters using where and wherebetween. If the user doest not enter the value in whereBetween it should not be in url.
Here's my Controller:
$prod = $request->input('productfm');
$sub = $request->input('sub-family');
$location = $request->input('location');
$thickness = [$request->input('minthick'), $request->input('maxthick')];
$width = [$request->input('minwidth'), $request->input('maxwidth')];
$weight = [$request->input('minweight'), $request->input('maxweight')];
// dd($prod);
$products = Product::where('state_id', '=', '1')
->when(!empty($prod), function ($query) use ($prod) {
return $query->where('product_family', $prod);
})
->when(!empty($sub), function ($query) use ($sub) {
return $query->where('sub_family', $sub);
})
->when(!empty($location), function ($query) use ($location) {
return $query->where('location', $location);
})
->when(!empty($thickness), function ($query) use ($thickness) {
return $query->whereBetween('thick', $thickness);
})
->when(!empty($width), function ($query) use ($width) {
return $query->whereBetween('width', $width);
})
->when(!empty($weight), function ($query) use ($weight) {
return $query->whereBetween('weight', $weight);
})
->get();
All fields are a select input in form. If I keep $prod, $sub_family and $location it works. But it's not working in whereBetween range filter.
URL still shows empty input of range filters and results don't come-up.
How do I make it clean/dynamic url? On dd($product) it returns empty array.
I'm trying to filter products based on query string. My goal is to get products from a collection if it's given, otherwise get every product. Could someone help me what's wrong with the following code?
$products = \App\Product::where([
'collection' => (request()->has('collection')) ? request('collection') : '[a-z]+',
'type' => (request()->has('type')) ? request('type') : '[a-z]+'
])->get();
PS.: I've also tried with 'regex:/[a-z]+', it's not working...
$products = \App\Product::where(['collection' => (request()->has('collection')) ? request('collection') : 'regex:/[a-z]+'])->get();
What you can do is use when eloquent clause, so your where clause for collections will be triggered only when the request('collection') exists, same logis applie to type as well.
$products = \App\Product::
when(request()->has('collection'), function ($q) {
return $q->where('collection', request('collection'));
});
->when(request()->has('type'), function ($q) {
return $q->where('type', request('type'));
})
->get();
Or another way if you have your request values assigned to a variable something like:
$collection = request('collection');
$type= request('type');
$products = \App\Product::
when(!empty($collection), function ($q) use ($collection) {
return $q->where('collection', $collection);
});
->when(!empty($type), function ($q) use ($type) {
return $q->where('type', $type);
})
->get();
So I'm making a fliter in laravel for a project and me and my teacher are braking our head on a the following thing.
In the code below the general search for a player works but the other statements won't add to it if they are defined and in the POST request;
Controller:
namespace App\Http\Controllers;
use App\Http\Requests;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Input;
class FilterController extends Controller
{
public function filter(Request $request)
{
$player = new \App\Player;
$filters = $player->newQuery();
$query = Input::get('q');
// Search for a player based on their status.
if ($request->has('status')) {
$filters->orwhere('status', $request->input('status'));
}
// Search for a player player on their club.
if ($request->has('club')) {
$filters->orwhere('Club', $request->input('club'));
}
// Search for a player player on their team category .
if ($request->has('Category')) {
$filters->orwhere('Category', $request->input('Category'));
}
// Search for a player player if he is flagged as removed.
if ($request->has('remove')) {
$filters->orwhere('remove', $request->input('remove'));
}
// Search for a player player on their size.
if ($request->has('size')) {
$filters->orwhere('Size', $request->input('size'));
}
// General search for a player
if($request->has('q')){
$filters->orwhere('first_name','LIKE','%'.$query.'%')
->orWhere('last_name','LIKE','%'.$query.'%')
->orWhere('mobile','LIKE','%'.$query.'%')
->orWhere('street_name_nummer','LIKE','%'.$query.'%')
->orWhere('city','LIKE','%'.$query.'%');
}
// Get the results and return them.
$results = $filters->get();
if(count($results) > 0){
return view('lists/ekick')->withDetails($results,$query);
} else return view ('lists/ekick')->with('No Details found. Try to search again !');
}
}
route:
Route::any('lists/ekick', 'FilterController#filter');
output view:
img from view
To pick up on Aaron Sarays answer, you are most likely filtering the wrong way. Normally additional filters are additional conditions each record has to meet in order to be part of the result. If you consider an Excel table and you filter one column, you won't even have all options to filter for in the second column because you already limited the result and you can only limit it further.
Combine this knowledge with an improved way of filtering and you receive a query like this:
public function filter(Request $request)
{
$query = $request->input('q');
$results = \App\Player::query()
->when($request->input('status'), function ($query, $status) {
$query->where('status', $status);
})
->when($request->input('club'), function ($query, $club) {
$query->where('club', $club);
})
->when($request->input('category'), function ($query, $category) {
$query->where('category', $category);
})
->when($request->input('remove'), function ($query, $remove) {
$query->where('remove', $remove);
})
->when($request->input('size'), function ($query, $size) {
$query->where('size', $size);
})
->when($query, function ($query, $q) {
$query->where(function ($query) use ($q) {
$query->where('first_name', 'LIKE', "%$q%")
->orWhere('last_name', 'LIKE', "%$q%")
->orWhere('mobile', 'LIKE', "%$q%")
->orWhere('street_name_number', 'LIKE', "%$q%")
->orWhere('city', 'LIKE', "%$q%");
});
})
->get();
if ($results->isNotEmpty()) {
return view('lists/ekick')->withDetails($results, $query);
} else {
return view ('lists/ekick')->with('No Details found. Try to search again !');
}
}
The function when($condition, $callback) as used in the query above is used to dynamically build queries. You can consider the following two statements equivalent:
// option 1: conditional query (preferred!)
$results = Player::query()
->when($request->input('q'), function ($query, $q) {
$query->where('name', 'LIKE', "%$q%");
})
->get();
// option 2: plain php query building... (not very clean code)
$query = Player::query();
if ($request->input('q')) {
$query->where('name', 'LIKE', '%'.$request->input('q').'%');
}
$results = $query->get();
In order to do what you're doing, I think you want to not use or with your queries. You're basically saying
Give me the Player where status is something or size is something
I think what you mean to say is
Give me the Player where status is something and size is something
Depending on if the requirements exist or not in the filter.
So, you'd want to alter your code using the following as an example:
if ($request->has('status')) {
$filters->where('status', $request->input('status'));
}
// Search for a player player on their club.
if ($request->has('club')) {
$filters->where('Club', $request->input('club'));
}
You can also bypass one step by using this:
$query = \App\Player::getQuery();
I have built a multi filter search for my website but I cant seem to find any documentation on multiple if statements inside of where for my search.
Returns Lots of Results
$data = Scrapper::paginate(15);
Returns none.. need it to be this way to have where statements with IF see bellow.
$database = new Scrapper;
$database->get();
Example of what I want to do..
$database = new Scrapper;
if (isset($_GET['cat-id'])) {
$database->where('cat_id', '=', $_GET['cat-id']);
}
if (isset($_GET['band'])) {
$database->where('price', 'BETWEEN', $high, 'AND', $low);
}
if (isset($_GET['search'])) {
$database->where('title', 'LIKE', '%'.$search.'%');
}
$database->get();
Very similar to this: Method Chaining based on condition
You are not storing each query chains.
$query = Scrapper::query();
if (Input::has('cat-id')) {
$query = $query->where('cat_id', '=', Input::get('cat-id'));
}
if (Input::has('band')) {
$query = $query->whereBetween('price', [$high, $low]);
}
if (Input::has('search')) {
$query = $query->where('title', 'LIKE', '%' . Input::get($search) .'%');
}
// Get the results
// After this call, it is now an Eloquent model
$scrapper = $query->get();
var_dump($scrapper);
Old question but new logic :)
You can use Eloquent when() conditional method:
Scrapper::query()
->when(Input::has('cat-id'), function ($query) {
$query->where('cat_id', Input::get('cat-id'));
})
->when(Input::has('band'), function ($query) use ($hight, $low) {
$query->whereBetween('price', [$high, $low]);
})
->when(Input::has('search'), function ($query) {
$query->where('title', 'LIKE', '%' . Input::get('search') .'%');
})
->get();
More information at https://laravel.com/docs/5.5/queries#conditional-clauses