Reputation: 41
i have category and price and title search in one form they don't work except all is filled i want like if anything not filled it show all products not to return null array and here is the code
Controller
public function all_products(Request $request){
$products = Product::OrderBY('views','desc')->Paginate(8);
$cats = Category::OrderBY('id','asc')->Paginate(3);
$cat = Category::all();
$q=$request->q;
$from_price=(float)$request->from_price;
$to_price=(float)$request->to_price;
$category = $request->category_search;
if($request->has('q')){
$products = Product::where('title_'.App::getLocale(),'like','%'.$q.'%')
->whereBetween('price',[$from_price, $to_price])
->where('sub_category_id','like','%'.$category.'%')
->orderBy('views','desc')->Paginate(6);
}
if($category != NULL & $from_price == NULL & $to_price == NULL){
$products = Product::where('title_'.App::getLocale(),'like','%'.$q.'%')
->where('sub_category_id','like','%'.$category.'%')
->orderBy('views','desc')->Paginate(6);
// return dd($products);
}
if($category != NULL & $from_price != NULL & $to_price != NULL){
$products = Product::where('title_'.App::getLocale(),'like','%'.$q.'%')
->whereBetween('price',[$from_price, $to_price])
->where('sub_category_id', $category)
->orderBy('views','desc')->Paginate(6);
}
else{
$products = Product::OrderBY('views','desc')->Paginate(8);
}
if($request->get('sort') == 'price_asc'){
$products = Product::OrderBy('price','asc')->paginate(8);
}elseif($request->get('sort') == 'price_desc'){
$products = Product::OrderBy('price','desc')->paginate(8);
}elseif($request->get('sort') == 'popularity'){
$products = Product::OrderBy('views','desc')->paginate(8);
}elseif($request->get('sort') == 'newest'){
$products = Product::OrderBy('created_at','desc')->paginate(8);
}
$setting = Setting::all()->first();
$country = Country::with('city')->get();
return view('all',['products'=>$products,'cats'=>$cats,'category'=>$cat,'setting'=>$setting,'countries'=>$country]);
}
View
<div class="filter_col">
<form action="/product/all/">
<div class="inner_bt"><a href="#" class="open_filters"><i class="ti-close"></i></a></div>
<input type="text" placeholder="{{ __('all.type_to_search') }}" class="form-control" name="q" value="{{ old('q') }}"/>
<br>
<div class="filter_type version_2">
<h4><a href="#filter_1" data-toggle="collapse" class="opened">{{ __('all.Categories') }}</a></h4>
<div class="collapse show" id="filter_1">
<select name="category_search" class="form-control mb-2">
<option value="">{{ __('all.all_cat') }}</option>
@foreach($category as $cat)
<optgroup label="{{ $cat->title_en }}" value="{{ $cat->title_en }}">
@foreach($cat->subCategories as $subCategories)
<option value="{{ $subCategories->id }}">{{ $subCategories->sub_cat_en }}</option>
@endforeach
</optgroup>
@endforeach
</select>
</div>
<!-- /filter_type -->
</div>
<!-- /filter_type -->
<div class="filter_type version_2">
<h4><a href="#filter_4" data-toggle="collapse" class="closed">{{ __('all.Price') }}</a></h4>
<div class="collapse show" id="filter_4">
<input type="text" name="from_price" class="form-control from_price" value="1" placeholder="{{ __('all.From') }} 1 eur"/>
<br>
<input type="text" name="to_price" value="10000" class="form-control mb-2" placeholder="{{ __('all.To') }}"/>
</div>
</div>
<!-- /filter_type -->
<div class="buttons">
<input type="submit" class="btn_1" value="{{ __('all.Filter') }}"/> <a href="/product/all" class="btn_1 gray" @if(App::getLocale() == 'srb') style="font-size: 12px" @endif>{{ __('all.Reset') }}</a>
</div>
</form>
i have category and price and title search in one form they don't work except all is filled i want like if anything not filled it show all products not to return null array and here is the code
Upvotes: 0
Views: 429
Reputation: 572
This is because you are using (float) at this lines:
$from_price=(float)$request->from_price;
$to_price=(float)$request->to_price;
And this makes this variables 0.0 if they are null and 0.0 is not null.
so you can try this:
if(is_null($request->from_price) && is_null($request->to_price) && is_null($request->category_search))
{
$products = Product::OrderBY('views','desc')->Paginate(8);
}
Or this
if( !$request->has('from_price') && !$request->has('to_price') && !$request->has('category_search') )
{
$products = Product::OrderBY('views','desc')->Paginate(8);
}
Instead of else condition and change this lines:
if($category != NULL & $from_price == NULL & $to_price == NULL)
if($category != NULL & $from_price != NULL & $to_price != NULL)
To
if($request->has('category_search') & !$request->has('from_price') & !$request->has('to_price) )
if($request->has('category_search') & $request->has('from_price') & $request->has('to_price))
Upvotes: 1
Reputation: 3045
You are creating a new query object for each condition, which makes the logic puzzled and potentially produces unwanted results. What about conditionally building a single query like this using when:
public function all_products(Request $request)
{
list($field, $direction) = $this->getSortDirection();
$products = Product::when($request->has('q'), function ($query) {
return $query->where('title_'.App::getLocale(),'like','%'.$q.'%');
})
->when(!is_null($category), function ($query) use ($category) {
return $query->where('sub_category_id','like','%'.$category.'%');
})
->when(!empty($from_price) && !empty($to_price), function ($query) use ($from_price, $to_price) {
$query->whereBetween('price',[$from_price, $to_price])
});
->orderBy($field, $direction)
->paginate(8);
// ...
}
protected function getSortDirection()
{
if (request('sort') == 'price_asc') {
return ['price','asc'];
}
if (request('sort') == 'price_desc') {
return ['price','desc'];
}
if (request('sort') == 'popularity') {
return ['views','desc'];
}
if (request('sort') == 'newest') {
return ['created_at','desc'];
}
throw new \Exception("Cannot resolve the sort direction and the field to be sorted.");
}
Upvotes: 0