Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

abhigarg's avatar

Laravel | Conditional search query based on user role / status

Hi, team:

I have a scenario where user records can be pulled up based on requester's "admin" role. Short of writing an if/else query such as below, is there an elegant way to deal with this?

public function search(Request $request) { $this->validateSearchRequest($request);

    if (Auth::user()->isSuperAdmin()) {

        return User::where('fname', 'like', '%' . $request->search_keywords . '%')
            ->orWhere('lname', 'like', '%' . $request->search_keywords . '%')
            ->orderBy('fname')
            ->limit($this->defaultLimitTo)
            ->get();

    } else {

        return User::where('admin_id', Auth::id())
            ->orWhere('fname', 'like', '%' . $request->search_keywords . '%')
            ->orWhere('lname', 'like', '%' . $request->search_keywords . '%')
            ->orderBy('fname')
            ->limit($this->defaultLimitTo)
            ->get();

    }
}

Notice the additional where clause in the else scenario.

Can a decorator be written that can use isSuperAdmin() status and do conditional things without making the code an if/else mess?

Thank you.

0 likes
7 replies
bobbybouwmann's avatar

Yes there is

public function search(Request $request) 
{ 
    $this->validateSearchRequest($request);

    $query = User::query();

    if (!Auth::user()->isSuperAdmin()) {
        $query = $query->where('admin_id', Auth::id())
            ->orWhere('fname', 'like', '%' . $request->search_keywords . '%');
    } else {
        $query = $query->where('fname', 'like', '%' . $request->search_keywords . '%');
    }

    $users = $query->orWhere('lname', 'like', '%' . $request->search_keywords . '%')
        ->orderBy('fname')
        ->limit($this->defaultLimitTo)
        ->get();

    return $users;
}

Note: Since Laravel 5.5 you always must start a query with a where, you can't start with a orWhere. Therefore you need to setup the query here.

I think we can even improve this further, but for now I don't see anything that might look better!

Snapey's avatar

You can dry it up like


public function search(Request $request)
{
    $this->validateSearchRequest($request);

    $query = User::where('fname', 'like', '%' . $request->search_keywords . '%')
            ->orWhere('lname', 'like', '%' . $request->search_keywords . '%')
            ->orderBy('fname')
            ->limit($this->defaultLimitTo);

    if (Auth::user()->isSuperAdmin()) {

        $query->orWhere('admin_id', Auth::id());

    }


    return $query->get();

}

1 like
bobbybouwmann's avatar
Level 88

There is also a when method on the query builder which might make this look better!

$query = User::when(!Auth::user()->isSuperAdmin(), function ($query) use ($request) {
    return $query->where('admin_id', Auth::id());
})
    ->orWhere('fname', 'like', '%' . $request->search_keywords . '%');
    ->orWhere('lname', 'like', '%' . $request->search_keywords . '%')
    ->orderBy('fname')
    ->limit($this->defaultLimitTo)
    ->get();

I think this is it. I didn't tested it!

Documentation: https://laravel.com/docs/5.5/queries#conditional-clauses

1 like
abhigarg's avatar

Thank you @Snapey and @bobbybouwmann.

Here's what I have narrowed it down to:

  1. The following:
return User::when((Auth::user()->isSuperAdmin() == false), function ($query) {
    return $query->where('admin_id', Auth::id());
})
    ->where('fname', 'like', '%' . $request->search_keywords . '%')
    ->orWhere('lname', 'like', '%' . $request->search_keywords . '%')
    ->orderBy('fname')
    ->limit($this->defaultLimitTo)
    ->get();

produces:

"query" => "select * from `table` where `admin_id` = ? and `fname` like ? or `lname` like ? order by `fname` asc limit 50”

which did not do the job since the 'and' and 'or' clauses are getting mixed up and query is returning extraneous results.

  1. The following:
return User::when(
        (Auth::user()->isSuperAdmin() == false), function ($query) {
            return $query->where('admin_id', Auth::id());
        }
    )
    ->where(
        function ($query) use ($request) {
            return $query->orWhere('fname', 'like', '%' . $request->search_keywords . '%')
                ->orWhere('lname', 'like', '%' . $request->search_keywords . '%');
        }
    )
    ->orderBy('fname')
    ->limit($this->defaultLimitTo)
    ->get();

produces:

"query" => "select * from `table` where `admin_id` = ? and (`fname` like ? or `lname` like ?) order by `fname` asc limit 50"

and returns the correct results.

Essentially, this is grouping the search parameters (parentheses).

Laravel Docs: https://laravel.com/docs/5.5/queries#parameter-grouping

Snapey's avatar

ok, you clarified the requirements better. If this works then go with that.

bobbybouwmann's avatar

Aah indeed! Well glad you fixed it ;) It's always important to determine what you want to achieve and make that step as easy as possible!

Please or to participate in this conversation.