Reputation: 1999
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
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