Q:

Filter Laravel collection using checkboxes

Hi Im filtering a set of data in Laravel (5.7) using url parameters via a form submission.
Resources can have many CurriculumLevels and many Subjects, here is the code I am using to filter based on the selected checkboxes:
if($request->get('subjects') || $request->get('levels')) {
        $subjects = $request->get('subjects');
        $levels = $request->get('levels');
        $resources = Resource::whereHas('subjects', function($query) use ($subjects) {
                    return $query->whereIn('id', (array)$subjects);
                })
                ->orWhereHas('curriculumLevels', function($query) use ($levels) {
                    return $query->whereIn('id', (array)$levels);
                })
                ->get();
    }else {
        $resources = Resource::all();
    }

My questions:
A) Is this the best way to filter data based on a users selection?
B) The url generated from the form is ugly, how can I clean this up so it looks like subjects=1,2,3&levels=1,2,3?
/resources?subjects%5B%5D=6&subjects%5B%5D=7&levels%5B%5D=2&levels%5B%5D=4

C) After the form submission the checkboxes are no longer selected, how can I show the checked checkboxes using the url parameters?
Appreciate any help!

A:

A) Use scopes, it's more likely best option
// Model

public class Resource extends Model {
    public function scopeSelectedOptions($query, $input = [])
    {
        if(!empty($input)) {
            if(array_key_exists('subjects', $input)) {
                $query->whereHas('subjects', function($q) use ($input) {
                    return $q->whereIn('id', $input['subjects']);
                });
            }
            if(array_key_exists('levels', $input)) {
                $query->orWhereHas('curriculumLevels', function($q) use ($input) {
                    return $q->whereIn('id', $input['levels']);
                });
            }
        }

        return $query;
    }
}

// Controller code

public class ResourcesController extends Controller {
    public function index() {
        $resources = Resources::SelectedOptions(request()->all())->get();
    }
}

B) The RFC 3986 standard don't care if URL looks nice, you also should not if end user is not supposed to modify it (this never happens). Get parameters are not SEO friendly
C) You must pass it further, after POST request you do
return redirect()->back()->withInput(request()->except('_token')); // or something close to it

The withInput should be accessible through old() method

