Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

trevorpan's avatar

Put search filter buttons into session and return results

May very well be butchering this process ..

The app has a filter bar with a number of drop down menus which allow users to select a job of their interest. At one point, I had a FilterJobsController but later scrapped it, as you can only get to /jobs by selecting the filter buttons - there is no /jobs link. So, then it seemed having that logic in the JobsController made good sense.

Now, I've determined that in addition to showing the job results on the app's page, I'd like the data to also be available in JSON format for use with other sites.

I've discovered the menus need to be in the session, otherwise it's very annoying to have to re-select the menu of a users choice over and over. ResourceCollections are new to me, and I'm not sure how the user selections are put into the session while retrieving the data.

Do you have any experience with this? Am I on the right track?

<?php

namespace App\Http\Controllers;

use App\Job;
use App\Http\Resources\Job as JobResource;

class JobsController extends Controller
{
    protected $job;

    public function __construct()
    {
        $this->middleware('auth')->except(['index', 'show']);
    }
    

    public function index(Request $request)
    {
        $jobs = function () {
            return JobResource::collection(Job::oldest());
        };
        
    return view('jobs.index', [
            'jobs' => Job::where([
            ['bidded', request('bidded')],
            ['state', request('state')],
            ['city', request('city')],
            ['biddertype', request('biddertype')],
            ['job', request('job')],
            ['subjob', request('subjob')], 
            ])->paginate(3)
                ->onEachSide(3)
                ->appends([
                    'bidded' => request('bidded'),
                    'state' => request('state'),
                    'city' => request('city'),
                    'biddertype' => request('biddertype'),
                    'job' => request('job'),
                    'subjob' => request('subjob'),
            ])
        ]);
    }
<?php

namespace App\Http\Resources;

use App\Job;
use App\Http\Resources\Job as JobResource;
use Illuminate\Http\Resources\Json\ResourceCollection;

class JobCollection extends ResourceCollection
{
    /**
     * Transform the resource collection into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {

        $request->session()->put([
            'bidded' => 'bidded', 
            'state' => 'state', 
            'city' => 'city', 
            'biddertype' => 'biddertype', 
            'job' => 'job', 
            'subjob' => 'subjob'
        ]);

        return [
            'data' => $this->collection,
            'links' => [
                'self' => route('jobs.index'),
            ],
        ];
    }
}
<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class Job extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'jobtitle' => $this->jobtitle,
            'body' => $this->body,
            'projectaddress' => $this->projectaddress,
            'city' => $this->city,
            'state' => $this->state,
            'zipcode' => $this->zipcode,
            'biddertype' => $this->biddertype,
            'job' => $this->job,
            'subjob' => $this->subjob,
            'deadline' => $this->deadline
        ];   
    }
}
0 likes
22 replies
Snapey's avatar

how will other sites maintain session?

trevorpan's avatar

@JLRDW - ok, this is how job population was achieved before in the JobsController (prior to today's post):

public function index(Request $request)
    {
        $jobs = Job::oldest()
        ->filter(request(['month', 'year']))
            ->get();

    return view('jobs.index', [
            'jobs' => Job::paginate(3)->onEachSide(3)
            ], compact('jobs'));
}

After reviewing that stack article I've made some modifications. With this form request, is it wise to "re-validate" if the data was validated when a different user created a job originally? In this case, we're just trying to populate existing jobs already in the database, not create new ones.

Does this prevent malicious attacks?

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class FilterJobs extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'bidded' => 'required|integer'
            'state' => 'required',
            'city' => 'required',
            'biddertype' => 'required',
            'job' => 'required',
            'subjob' => 'required',
            //
        ];
    }
}

Added query scopes. I felt like these queries should be singular, and the controller collects an array - seem right?

// Job.php (model)

    public function scopeBidded($query, $bidded)
    {
        if (!is_null($bidded)) {
            return $query->where('bidded', 'bidded');
        }

        return $query;
    }

    public function scopeState($query, $state)
    {
        if (!is_null($state)) {
            return $query->where('state', 'state');
        }

        return $query;
    }

    public function scopeCity($query, $city)
    {
        if (!is_null($city)) {
           return $query->where('city', 'city');

        return $query;
    }

    public function scopeBidderType($query, $biddertype)
    {
        if (!is_null($biddertype)) {
            return $query->where('biddertype', 'biddertype');
        }

        return $query;
    }

    public function scopeJob($query, $job)
    {
        if (!is_null($job)) {
            return $query->where('job', 'job');
        }

        return $query;
    }

    public function scopeSubJob($query, $subjob)
    {
        if (!is_null($subjob)) {
            return $query->where('subjob', 'subjob');
        }

        return $query;
    }
//JobsController

    public function index(Request $request)
    {

    $jobs = Job::bidded($request->bidded)
                ->state($request->state)
                ->city($request->city)
                ->biddertype($request->biddertype)
                ->job($request->job)
                ->subjob($request->subjob);
    
    return view('jobs.index', [
            'jobs' => Job::where([
            ['bidded', request('bidded')],
            ['state', request('state')],
            ['city', request('city')],
            ['biddertype', request('biddertype')],
            ['job', request('job')],
            ['subjob', request('subjob')], 
            ])->paginate(3)
                ->onEachSide(3)
                ->appends([
                    'bidded' => request('bidded'),
                    'state' => request('state'),
                    'city' => request('city'),
                    'biddertype' => request('biddertype'),
                    'job' => request('job'),
                    'subjob' => request('subjob'),
            ])
        ]);

The above does not retrieve a job that exists in the database, but it also does not cause a whoops page either. I feel like this is a double query, not sure how to put the results into an array. Any ideas where it's going wrong?

jlrdw's avatar

I am not sure what:

    public function authorize()
    {
        return true;
    }

is doing. Do you have Auth middleware setup in your routes. I usually see code more like:

if (Auth::check()) {
    // do something
}

It is hard to visualize another's code and know exactly what they are doing and why.

I am guessing you not only have a job site, but are also sending this data to other job sites using their API.

I see you have taken quite a few lessons. That's why I also referred you to https://github.com/bestmomo/laravel5-5-example

In fact I myself just recently started using scopes, because of a suggestion snapey made. I am just starting to explore repositories.

You could probably set up queues to automate sending jobs.

Lookup events, queues, etc in the docs. Plus I am sure there are many tutorials around.

Step one is, do one thing at a time. Get your site working with the filters correctly.

Decide if you want to use the LIKE clause, or something like Elasticsearch. And on top of this, you have to implement RBAC.

So it's a learning curve.

Most of my searches are very simple, nothing like yours. As example, this was done a while back:

https://drive.google.com/file/d/0B1_PFw--3o74YjVreHNBOWU2aEE/view

I usually just do something like:

$query = Dog::where('dogname', 'like', $dogsch);
        if ($aval == "n") {
            $query->where('adopted', '=', 1);
        } else if ($aval == "y") {
            $query->where('adopted', '=', 0);
        }
        $dogs = $query->orderBy('lastedit', 'DESC')->paginate(5);

But scopes is a good start. A tip, Jeffrey's search is not as powerful as google, so if searching laravel, go to google and do this:

site:laracasts.com your search term

like

site:laracasts.com filtering eloquent results
trevorpan's avatar

@SNAPEY - Hi, I don't think that's possible - is it?

I read a post you replied about an actor or speaker website you were working on some time back. It maintained state between pages. That had the basic functionality I'm looking for this app.

I may be confusing what can be done with the JSON API, but I thought maybe the ResourceCollection could accomplish the filter bar/buttons and give the data in form of JSON like the class Job extends JsonResource (hopes) to do.

I read if you request JSON that another request is not needed as the payload has been delivered. But it also seems like perhaps only requesting the bare minimum would be better. e.g. jobtitle, deadline and then if someone likes that, they could request that job. (at the same time, this app is far from needing to worry about performance, at least at this stage.)

trevorpan's avatar

@JLRDW - cute pups. It's neat how the 'like' allowed you to type just the first letter for cat.

Ok, I saw that use of 'like' in the stackoverflow post you provided but this: 'return $query->where('bidded', 'like', '%'.$bidded.'%');`` yielded an error Array to string conversion. So I tried the above, but I feel it's not pulling the selected, the scope is looking for job the column name.

I may have made a mistake in the explanation. The filter bar is a drop down set of buttons with selects e.g. Job could have steel, lumber, plumbing, etc. So the user is unable to type a choice. (at least at this stage-maybe in the future).

On the authorize() it comes false from the artisan command, but if you have other middleware it said to turn it to true. https://laravel.com/docs/5.7/validation#form-request-validation (a little down the page).

jlrdw's avatar

Here's a couple of more related to searching:

https://laracasts.com/discuss/channels/eloquent/building-queries-with-multiple-search-filters

https://laracasts.com/discuss/channels/laravel/making-a-search-page-with-multiple-filters

There are more.

I used "LIKE" as example, just use "=" in your case. All you are doing is "using" the chosen search terms, and weeding out the ones users did not pick. The code could get fairly large.

Last one I tried is

site:laracasts.com filtering multiple search terms

Let google be your friend, all of us reach out for ideas.

It's neat how the 'like' allowed you to type just the first letter for cat.

That search was getting dogs where their name started with a "c".

If a "ch" entered, then only dogs who's name started with "ch".

But I'd consider a high power search engine, because it will find related things. I forget what it's called.

For Steel worker, you also want related items like, metal workers, metal fabrication, etc.

@snapey what is that search term called where similar things are found.

trevorpan's avatar

@JLRDW - Hi there, been working on this thing the last few days.

select * from `jobs` where `bidded` = '0' and `state` = 'Arizona' and `city` = 'Phoenix' and `biddertype` = 'Subcontractor' and `job` = 'Mechanical' and `subjob` = 'Material'

This query is returned based on the links you shared. It is the proper query but does not retrieve any results. (The values above are html selects)

//JobsController

protected $with = ['bidded', 'state', 'city', 'biddertype', 'job', 'subjob'];

public function __construct()
    {
        $this->middleware('auth')->except(['index', 'show']);
    }

public function index(Request $request)
    {
   $jobs = Job::bidded($request->bidded)
                    ->state($request->state)
                    ->city($request->city)
                    ->biddertype($request->biddertype)
                    ->job($request->job)
                    ->subjob($request->subjob)
                    ->get();

    $request->session()->put([
            'bidded' => request('bidded'),
            'state' => request('state'),
            'city' => request('city'),
            'biddertype' => request('biddertype'),
            'job' => request('job'),
            'subjob' => request('subjob'),
    ]);

    return view('jobs.index', compact('jobs'));
}
//Job.php (model) - all other methods have same format

    public function scopeBidded($query, $bidded)
    {
        if (!is_null($bidded)) {
            return $query->where('bidded', $bidded);
        }

        return $query;
    }

EDIT: At this point the session and query return the same things. However, they are not rendered to the view. I'm at a loss, the docs show this same type of query chaining.

Snapey's avatar

Hi

If you are not already doing so, installing Laravel Debugbar will really help. It will show you all queries and also the session state.

I find it invaluable

trevorpan's avatar

@SNAPEY - Yea, I love it, too.

This is what the query says (it also shows an auth query, but that's not an issue):

select * from `jobs` where `bidded` = '0' and `state` = 'Arizona' and `city` = 'Phoenix' and `biddertype` = 'GeneralContractor' and `job` = 'Lumber' and `subjob` = 'Material'

The session shows the selected dropdowns each time they are changed.

_token
    HePISm5UdwWOUlAzUZsPzU9d32UoY7aA1vzsDx3s
_previous
    array:1 [ "url" => "http://bidbird.test/jobs?_token=HePISm5UdwWOUlAzUZsPzU9d32UoY7aA1vzsDx3s&bidde...
_flash
    array:2 [ "old" => [] "new" => [] ]
bidded
    array:1 [ 0 => "0" ]
state
    array:1 [ 0 => "Arizona" ]
city
    array:1 [ 0 => "Phoenix" ]
biddertype
    array:1 [ 0 => "GeneralContractor" ]
job
    array:1 [ 0 => "Lumber" ]
subjob
    array:1 [ 0 => "Material" ]
login_web_59ba36addc2b2f9401580f014c7f58ea4e30989d
    1
PHPDEBUGBAR_STACK_DATA
    []

When I dd($jobs, $request); (in JobsController@index) I get this below - which seems like it's never talking to the database, as the array is empty - there's two test jobs.

Is that how you would interpret this response?

Collection {#557 ▼
  #items: []
}

// relevant array data on another test

 #session: Store {#489 ▼
    #id: "sjTKpjiW2R1NbxG223hR2cuqaPOII1g9aQcMLSn0"
    #name: "bidbird_session"
    #attributes: array:10 [▼
      "_token" => "HePISm5UdwWOUlAzUZsPzU9d32UoY7aA1vzsDx3s"
      "_previous" => array:1 [▶]
      "_flash" => array:2 [▼
        "old" => []
        "new" => []
      ]
      "bidded" => array:1 [▼
        0 => "0"
      ]
      "state" => array:1 [▼
        0 => "Arizona"
      ]
      "city" => array:1 [▼
        0 => "Phoenix"
      ]
      "biddertype" => array:1 [▼
        0 => "Subcontractor"
      ]
      "job" => array:1 [▼
        0 => "Mechanical"
      ]
      "subjob" => array:1 [▼
        0 => "Material"
      ]
jlrdw's avatar

@TREVORPAN - I don't see session in the scope, but if all those parameters are used, they are passed like this:

 public function pdotest()
    {
        $petowner = 'diane';
        $params = [
            'petowner' => $petowner
        ];
         $pets = Pet::getMyPets($params);
         
         foreach ($pets as $r) {
            echo $r->petowner . "<br>";
        }
        exit();

scope:

    public function scopegetMyPets($query, $params)
    {
        return $query->where($params)->get();
        
    }
    

Just quick example I worked up, and just one parameter.

I wouldn't use session, unless you need the data again somewhere.

The problem is what if some parameters are left out, you need to work on this with some if statements and work up a query to test for conditions.

Tested with 2 parameters:

$petowner = 'diane';
        $params = [
            'petowner' => $petowner,
            'petname' => 'HOGAN'
        ];
         $pets = Pet::getMyPets($params);
         
         foreach ($pets as $r) {
            echo $r->petowner . " | " . $r->petname . "<br>";
              
        }
        exit();

output:

DIANE | HOGAN

So just take time and work it out, don't rush.

trevorpan's avatar

@JLRDW - could you clarify "don't see session in the scope"? In your pdetest() are you saying all the local scopes can be combined there and then you could call $jobs = Job::pdotest()->get;?

on a new finding - I'm wondering if the pagination is causing this. After reading a few posts about getCollection() not available I read the get()request on the controller returns an array, so the @blade call fails. The other possible issue I found is array_* is being phased out. (I've upgraded to 5.8)

//index.blade.php
    @foreach(array_chunk($jobs->getCollection->all(), 3) as $page)

    @foreach ($jobs as $job) 
           @include ('jobs.job')
    @endforeach

    <div class="pagenumbers">
            {{ $jobs->links() }}
    </div>

        @endforeach

man, this stuff fun and crazy frustrating at the same time!

EDIT @jlrdw I'll take a break, going since this morning, but WILL solve this! thank you very much and also @snapey

jlrdw's avatar

could you clarify "don't see session in the scope

You created a session array, I just don't see where you are using session in the scope to retrieve the array.

As far as pagination, you don't use ->get you use paginate->(5); 5 is just example.

You have to pass the parameters to the view and append the pagination links:

Example if you have something like:

$searchparams = [':search' => $search];

$searchparams is passed to the view and appended to links:

{{ $dogs->appends($searchparams)->links() }}

Gives you something like:

yoursite.com/dogs/index?search=c&page=2

Work more examples from docs, practice paginating something simple first. This stuff is easy once learned, but build up in small steps. Don't do too much too fast.

Snapey's avatar

remember that all your scope statements are AND logic so it only takes one of them to be wrong to exclude any results.

I would take scopes out, make sure you get the results you expect and then re-introduce them one by one.

trevorpan's avatar

@SNAPEY - The WINNER:

public function index(Request $request, Job $job)
    {
        $request->session()->put([
                'bidded' => request('bidded'),
                'state' => request('state'),
                'city' => request('city'),
                'biddertype' => request('biddertype'),
                'job' => request('job'),
                'subjob' => request('subjob'),
            ]);

        $jobs = Job::bidded($request->bidded)
                ->state($request->state)
                ->city($request->city)
                ->biddertype($request->biddertype)
                ->job($request->job)
                ->subjob($request->subjob)
                ->paginate(3)
                ->appends([
                       'bidded' => request('bidded'),
                       'state' => request('state'),
                       'city' => request('city'),
                       'biddertype' => request('biddertype'),
                       'job' => request('job'),
                       'subjob' => request('subjob')
                ]);

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

So, your method of starting with the first item bidded and then state etc found the error. Multiple errors. Egregious things like capital State instead of lowercase state, etc. and after fixing that found that material was materials! (in the DB)

So that works. Thank you`

But the original post sought to put the selection into a session so the filter button, html selects, would stay populated.

Am I on the right track for that?

I've read that's generally done with ajax, but I'm not familiar. Is there a laravel way?

Snapey's avatar

As you mentioned, the site https://speakernet.co.uk manages filters using the session, and I recently refactored it to use ajax to change the filter. Its only a small application (about 1700 records in the largest table) so in the main talks listing, changing the filter causes a complete page reload.

On the map page its slightly different as it uses ajax to refetch the markers and replots them on the map already in view.

The filter mechanism is the same though and there is a couple of routes;

Route::post('/filter','FiltersController@create')->name('filter.create');
Route::delete('/removefilter/{filter}','FiltersController@destroy')->name('filter.destroy');

which lead to the FiltersController. This is responsible for setting the filter state in session, then when the map pins are requested, or the grid reloaded, the controller will use any filters present.

The filtersController;

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Traits\TalksHelpers;
use Illuminate\Http\Request;

class FiltersController extends Controller
{
    use TalksHelpers;

    public function create(Request $request)
    {
        $this->initialiseFilters();

        if($request->has('cat')){
             $this->filters['category'] = $request->cat;
        }

        if($request->has('fee')){
             $this->filters['fee'] = $request->fee;
        }

        if($request->has('region')){
             $this->filters['region'] = $request->region;
        }

        if($request->has('recency')){
             $this->filters['recency'] = $request->recency;
        }

        if($request->has('notice')){
             $this->filters['notice'] = $request->notice;
        }

        $this->setFilteredFlag();

        $this->saveFilters();

        return enumerate_filters($this->filters);

    }

    public function destroy(Request $request, $filter)
    {
        $this->unsetFilter($filter);
        $this->setFilteredFlag();
        return enumerate_filters($this->filters);
    }
}

This calls on a Trait which is also shared by the grid controller

<?php
namespace App\Http\Controllers\Traits;

use App\Fee;
use App\Category;
use App\Region;
use App\Tag;

trait TalksHelpers
{

    protected $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());
    }

    public function preparePotLuck()
    {
        view()->share('potLuck', Tag::inRandomOrder()->take(25)->pluck('name', 'slug'));
    }


    public function initialiseFilters()
    {
        //ensure that the filters are setup in session and hydrated into controller
        $this->filters = session('filters');
        if(!isset($this->filters)) {
            $this->resetFilters();
        }
    }

    private function resetFilters()
    {
        // create empty filters
        $this->filters = [
            'category' => '',
            'fee' => '',
            'region' => '',
            'recency' => '',
            'notice' => '',
            'tagged' => '',
            'filtered' => false]
        ;

        session(['filters' => $this->filters]);
    }

    private function saveFilters()
    {
        // save updated filters to the session
        session(['filters' => $this->filters]);
    }

    private function unsetFilter($filter)
    {
        $this->initialiseFilters();
        $this->filters[$filter] = '';
        $this->setFilteredFlag();
        return $this->saveFilters();
    }

    private function setFilteredFlag()
    {
        $f = $this->filters;

        if (!
            empty($f['region'])
            || !empty($f['category'])
            || !empty($f['fee'])
            || !empty($f['recency'])
            || !empty($f['notice'])
            || !empty($f['tagged']))
         {
            return $this->filters['filtered']= true;
        }
        return $this->filters['filtered']= false;
    }


}

Javascript from the grid view;

@section('page-js')
    <script>

        window.onload = function () {

            $('#category').on('change', function(){
                applyFilter('cat=' + this.value);
            });

            $('#fee').on('change', function(){
                applyFilter('fee=' + this.value);
            });
            
            $('#region').on('change', function(){
                applyFilter('region=' + this.value);
            });
            
            $('#recency').on('change', function(){
                applyFilter('recency=' + this.value);
            });
            
            $('#notice').on('change', function(){
                applyFilter('notice=' + this.value);
            });

        }

        function applyFilter(filter)
        {
            axios.post('/filter?' + filter)
                .then(function(response){
                    location.reload();
                });
        }

        function removeFilter(filter)
        {
            axios.delete('/removefilter/' + filter)
                .then(function(response){
                    if(filter == 'category') {
                        location.replace('{{ route('talks.index') }}');
                    } else {
                        location.reload();
                    }
                });
        }

    </script>

    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

@endsection

and then the grid TalksController (just the relevant bits)

    use TalksHelpers;

    protected $status;

    //list all the available talks (topics)
    public function index(Request $request)
    {
        $this->initialiseFilters();
        return $this->talks();
    }

    /**
     * gather details for the main listing view
     * @return view
     */
    public function talks()
    {
        $filters = $this->filters;

        // get topics, filtered by adding local scopes through the Topic class 
        $talks = Topic::with('speaker.region','tagged','category')    
                        ->regions($filters['region'])
                        ->category($filters['category'])
                        ->fee($filters['fee'])
                        ->recency($filters['recency'])
                        ->tagged($filters['tagged'])
                        ->published()
                        ->notice($filters['notice'])
                        ->orderBy('subject')
                        ->paginate(15);

        $this->prepareDropdowns();

        $this->preparePotLuck();

        if(isset($filters['tagged'])){
            view()->share('siteTitle', "SpeakerNet - index of talks tagged {$filters['tagged']}");
        } else {
            view()->share('siteTitle', 'SpeakerNet - your source for interesting speakers');
        }

        return view('guest.talks')->with(compact('talks','region'))
            ->withFilters($filters)
            ->withEnumeratedFilters(enumerate_filters($filters));
    }

edit: Some of the simpler model scopes

    public function scopeCategory($query,$category)
    {
        if($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;
    }

Sorry, a lot of code. Hopefully you will pick up some ideas

trevorpan's avatar

@SNAPEY - @SNAPEY - good morning`

//Session data via Laravel Debugbar
array:7 [
  "bidded" => "0"
  "state" => "arizona"
  "city" => "tucson"
  "biddertype" => "subcontractor"
  "job" => "materials"
  "subjob" => "lumber"
  "filtered" => false
]

I'm a bit confused by this. The dropdowns do not stay set after clicking the submit button, though I've integrated the basic concepts and can still retrieve jobs.

How do you bind the session to the dropdowns?

here's a sample dropdown:

 <select class="selectx" name="job" id="job" required>
            <option class="optionx" value="">(5) Job</option>
            <option class="optionx" id="materials" value="materials">Materials</option>
</select>

I found some ajax videos which prefixed the selects with id="sel_materials"but that (sel_) did not seem to affect anything.

In your function applyFilter() you are posting the html select to the session right? Not posting to the db? I find this a little confusing as the JobsController uses a get request to retrieve records from the db.

Or is the issue that the above form uses a submit button and your's filters at each dropdown?

Snapey's avatar

Sorry, missed that bit. When the view is loaded for the first time, the select boxes are all preselected using blade.

Only later when they are changed, the ajax is fired to the server to tell the server what the filters look like now, but because this is on-change then the dropdown has already been changed and I therefore never need to set the dropdowns in ajax.

The filter select boxes all have this type of setup;

    {{-- category dropdown selector --}}
    <div class="form-group">
        <label class="col-sm-4 control-label" for="category">Category</label>
        <div class="col-sm-8">
            <select class="form-control input-sm" id="category" name="category">
                <option value="">Any</option>
                @foreach($categoryList as $cat)
                    <option value='{{ $cat->id }}'
                        @if($filters['category']!="" && $filters['category'] == $cat->id)
                            selected="selected"
                        @endif
                        >
                        {{ $cat->name }}</option>
                @endforeach
            </select>
        </div>
    </div>

It inserts 'selected' into the option if the category filter contains the current option

1 like
trevorpan's avatar

@SNAPEY - May have it wrong - it seems if you're looping then a specific table, only for populating lists, would look like this?

(this is an attempt to reverse engineer what you're showing, so I understand how you get that functionality)

class CreateFeesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('fees', function (Blueprint $table) {
           $table->increments('id');
       $table->string('name');
           $table->boolean('free');
           $table->boolean('expensed');
           $table->boolean('paid');
       $table->boolean('unknown');
           $table->timestamps();
        });
    }
//CategoriesConroller.php

public function index (Request $request)
{
    $categoryList = Fee::get([
        'name' => $request('name'),
        'free' => $request('free'),
        'expensed' => $request('expensed'),
        'paid' => $request('paid'),
        'unknown' => $request('unknown')
        ]);

    return view('speakers.indes', compact('categorylist');
}

This could be a total botch here - are the child <select> values column names from the <option> in the fees table ?

Snapey's avatar

So I have a Model of Topics (talks) and this belongs to Category model, belongs to Region, has an updated_at column etc

Using the filters, the user can narrow down their search.

In order to show a dropdown of, for instance the categories, I use View share of the categories table (in the prepareDropdowns() function

        view()->share('categoryList',Category::orderBy('name','ASC')->get());

So in the view I have access to the full list of the categories I want the user to choose from

trevorpan's avatar

@SNAPEY - Alright, cool. This should be enough to get this thing figured out. Thank you very much `

Please or to participate in this conversation.