Moataz X9
Moataz X9

Reputation: 41

laravel search not working if anthing is null in the 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
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

Answers (2)

Behzad
Behzad

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

Kevin Bui
Kevin Bui

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

Related Questions