Oscar
Oscar

Reputation: 61

Laravel - passing array of columns in 'where' clause

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

Answers (3)

Jerodev
Jerodev

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

Marcin Nabiałek
Marcin Nabiałek

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

Jordan Lipana
Jordan Lipana

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

Related Questions