Jesse Luke Orange
Jesse Luke Orange

Reputation: 1999

Laravel 5.6 search forms

In an app I'm working on there are two main searches: a site wide search and a quick search.

Quick search

The quick search has to take the role, user and department and return all the users that match the criteria. I already see a potential problem in the fact that you could select a role that isn't in a department... but anyway.

This is what I've tried.

public function userSearch(Request $request)
{
    $department = $request->get('department');
    $role = $request->get('role');
    $location = $request->get('location');

    $users = User::where('department', $department)
                    ->where('role', $role)
                    ->where('location', $location)
                    ->get();

    foreach($users as $user)
    {
        echo '<br />' . $user->username;
    }

}

It gets complicated though as user, role and department are drop down boxes and may not have had anything selected.

So If I search for just Digital as a department the query string is:

http://127.0.0.1:8000/usersearch?department=Digital&role=&location=

Obviously, this doesn't return anything as I'm using multiple where clauses.

Would I have to individually check whether each variable is empty and construct the query? This seems a bit sketchy as I'd have to check every possible order to get the query right.

Site wide search

The other search is a site search that takes one query string, here is my stupidly basic method startings:

public function search(Request $request)
{
    $search = $request->get('q');

    return view('pages.search.index', compact('search'));

}

I read in the Laravel documentation that there is a package available called Scout but is there a more rudimentary way to just get everything from every model, given the query string?

Things I'd like to return:

I have models associated to database tables for all the above so could I just do the following?

users = User::where('name', 'like', '%' . Input::get('name') . '%')
              ->orWhere('name', 'like', '%' . Input::get('name') . '%')

articles= Article::where('name', 'like', '%' . Input::get('name') . '%')
                  ->orWhere('name', 'like', '%' . Input::get('name') . '%')

and so on...

Then when displaying results just do:

return('nameofview', compact('users', 'articles')

Or is this likely to be slow and cumbersome?

Update

For the site-wide search, for now, I just have:

public function search(Request $request)
{
    $search = $request->get('q');

    $users = User::where('username', 'like', '%' . $request->get('q') . '%')
                ->orWhere('displayName', 'like', '%' . $request->get('q') . '%')
                ->orWhere('email', 'like', '%' . $request->get('q') . '%')
                ->orWhere('role', 'like', '%' . $request->get('q') . '%')
                ->orWhere('department', 'like', '%' . $request->get('q') . '%')
                ->orWhere('location', 'like', '%' . $request->get('q') . '%')
                ->orWhere('directDialIn', 'like', '%' . $request->get('q') . '%')
                ->orWhere('mobileNumber', 'like', '%' . $request->get('q') . '%')->get();


    return view('pages.search.index', compact('search', 'users'));

}

For the quick search, I added some query scopes

/**
 * Scope a query by department
 */
public function scopeByDepartment($query, $department)
{
    return $query->where('department', $department);
}

/**
 * Scope a query by role
 */
public function scopeByRole($query, $role)
{
    return $query->where('role', $role);
}

/**
 * Scope a query by location
 */
public function scopeByLocation($query, $location)
{
    return $query->where('location', $location);
}

Upvotes: 0

Views: 742

Answers (1)

cherrysoft
cherrysoft

Reputation: 1195

There is a much better way to achieve what you are looking to do using a combination of conditional clauses and scopes. For example...

User::all()->when(isset($request->department), function ($q) use ($request) {
    $q->byDepartment($request->department);
})
->when(isset($request->role), function($q) use ($request) {
    $q->byRole($request->role);
});

Once you set up your scopes on the model you can now selectively filter by any number of the request variables so you don't have to worry if it is not set. This also keeps your code much more compact.

Upvotes: 1

Related Questions