Reputation: 61
I have a search query like this:
$data = User::where('first_name', 'like', '%'.$query.'%')
->orWhere('last_name', 'like', '%'.$query.'%')
->get();
Now, I have many models, each with different column names. Instead of defining a search()
function into every controller, I want to do this:
// User
public static function searchableFields()
{
return ['first_name', 'last_name'];
}
// Some other model
public static function searchableFields()
{
return ['name', 'description'];
}
And put the search logic in a shared controller, something like this:
$data = $classname::
where($classname::searchableFields(), 'like', '%'.$query.'%')
->get();
How can I achieve this?
Thanks a lot.
Upvotes: 0
Views: 6421
Reputation: 33196
You can loop over the fields and add them to your Eloquent query one by one.
$data = $classname::where(function ($query) use ($classname) {
foreach ($classname::searchableFields() as $field)
$query->orWhere($field, 'like', '%' . $query . '%');
})->get();
Upvotes: 4
Reputation: 111859
I would use scope for that.
You can create base model that all the models should extend (and this model should extend Eloquent model) and in this model you should add such method:
public function scopeMatchingSearch($query, $string)
{
$query->where(function($q) use ($string) {
foreach (static::searchableFields() as $field) {
$q->orWhere($field, 'LIKE', '%'.$string.'%');
}
});
}
Now you can make a search like this:
$data = User::matchingSearch($query)->get();
Just to avoid confusion - $query
parameter passed to matchingSearch
becomes $string
parameter in this method.
Upvotes: 1
Reputation: 447
You can try something like this.
// Controller
function getIndex(Request $request)
{
$this->data['users'] = User::orderBy('first_name','asc')->get();
if ($request->has('keyword')) {
$results = User::search($request->keyword);
$this->data['users'] = collect([$results])->collapse()->sortBy('first_name');
}
}
// Model
function search($keyword)
{
$results = [];
$search_list = ['first_name','last_name'];
foreach ($search_list as $value)
{
$search_data = User::where($value,'LIKE','%'.$keyword.'%')->get();
foreach ($search_data as $search_value) {
$exist = 0;
if (count($results)) {
foreach ($results as $v) {
if ($search_value->id == $v->id) {
$exist++;
}
}
if ($exist == 0) {
$results[] = $search_value;
}
} else{
$results[] = $search_value;
}
}
}
return $results;
}
Upvotes: 0