afujita's avatar

How to retrieve records filtered by selected value

This is commonly used in e-commerce sites, like serarching products based on some category. Well, what I want to retrieve is, for example, all products that belongs to books, if I select books. I think I have to insert some if statements in Controller in order for each submit action, but not sure.

Here is what I have up to now...

View

{!! Form::open(['method' => 'GET', 'route'=>'products', 'class' => 'navbar-form']) !!}
    {{ Form::select('category_id', [
         '' => 'select category,
         '1' => 'books',
         '2' => 'clothes',
          '3' => 'eletronics'],
    null, ['class' => 'form-control'])
          }}
     {{ Form::submit('submit, ['class' => 'submit btn']) }}
  {!! Form::close() !!}

ProductsController

pubic function search()
    {
        $products = Product::all();
        $products->category_id = Input::get('category_id');

        return view('products.index', compact('products'));
    }

Route

Route::get('products', ['as' => 'products', 'uses' => 'ProductsController@products']);

Appreciate your help.

0 likes
6 replies
afujita's avatar

@tomi Thanks for your reply and for the links! And sorry for not been clear. Actually, I'm using Eloquent (one to many) and using foreach loop in my view… But what I don't know is how to filter my results based on the selected value. For example, If I select books and click submit, all records (products) that belong to the books category get retrieved, but if select electronics, I get all electronics products in my view. That's why I think I need to use some if statement for the filtering…. May something like this, but in a eloquent way..

<form action="#" method="post">
<select name="Category">
<option value="books">Books</option>
<option value="clothes">Clothes</option>
<option value="electronics">Eletronics</option>
</select>
<input type="submit" name="submit" value="Get Selected Values" />
</form>
<?php
if(isset($_POST['submit'])){
$selected_val = $_POST['books'];  
echo  …. ;  
ifelse (isset($_POST['submit'])){
$selected_val = $_POST['clothes'];  
echo  …. ;  
}
?>
tomopongrac's avatar

i would do that in controller

$category_id = $Input::get('Category');

$products = App\Category::find($category_id)->products;

products is your name of relationship

afujita's avatar

@tomi Thanks again for your suggestion. Actually tried this one bellow and worked…

$products = Product::where('category_id', Input::get('category_id'))->get();
Snapey's avatar

Use scopes. Here is an example lifted from a project where I have dropdowns on the front page. There are four dropdowns, region, fees category and updated. The topics model has scopes that restrict by any combination of these.

controller;

    /**
     * return a view of talks after receiving a list of filters
     * @param  Request $request form posting with filters to be applied
     * @return [type]           returns a view with the selected filter applied
     */
    public function search(Request $request)
    {
        $filters = ['region' => $request->region,
                    'category' => $request->category,
                    'fee' => $request->fee,
                    'recency' => $request->recency];   


        // get topics, filtered by adding local scopes through the Topic class 
        $talks = Topic::with('speaker','tagged','category')    
                        ->region($request->region)
                        ->category($request->category)
                        ->fee($request->fee)
                        ->recency($request->recency)
                        ->orderBy('subject')
                        ->get();

        $this->prepareDropdowns();

        return view('guest.talks')->with(compact('talks','region','filters'));

    }

    public function prepareDropdowns()
    {
        view()->share('feelist', Fee::all());
        view()->share('categorylist',Category::orderBy('name','ASC')->get());
        view()->share('regionList',Region::orderBy('sort','ASC')->get()); 
    }

and then the scopes from the model;

    public function scopeRegion($query,$region)
    {
        if(!Empty($region)){
            //get the region
            $reg = Region::where('regioncode', $region)->first();

            return $query->whereHas('speaker', function ($query) use ($reg) {
                        $query  ->where('region_id', $reg->id);
                     })->orWhereHas('speaker', function ($query) use ($reg) {
                        $query  ->where('region_id', $reg->childof);
                     });
        }
        return $query;
    }

    public function scopeCategory($query,$category)
    {
        if(!Empty($category)){
            return $query->where('category_id',$category);
        }
        return $query;
    }

    public function scopeFee($query,$fee)
    {
        if(!Empty($fee)){
            return $query->where('fee_id',$fee);
        }
        return $query;
    }

    public function scopeRecency($query,$recency)
    {
        if(!Empty($recency)){
            $cutoff = Carbon::now()->subDays($recency)->format('Y-m-d');
            return $query->where('updated_at','>',$cutoff);
        }
        return $query;
    }

The region one is a little complicated because there are two levels of region to consider, but the others should give you an idea.

In each, the scope first checks if the user has specified a constraint, otherwise the scope is added to the query.

afujita's avatar

Thank you very much, @Snapey , for your kind suggestion. Will keep with your idea for further studying!!

Please or to participate in this conversation.