Nested 'AND OR' Query in Eloquent

You were very close to the answer

$challenge = $this->challenges()
        ->where('open', true)
        ->where(function($q) use ($user_id, $opponent_id) {
            $q->where(function($query) use ($opponent_id, $user_id){
                    $query->where('player_1', $user_id)
                          ->where('player_2', $opponent_id);
                })
              ->orWhere(function($query) use ($opponent_id, $user_id) {
                    $query->where('player_1', $opponent_id)
                          ->where('player_2', $user_id);
                });
            })
        ->first();

Here are the differences between two codes


I needed the nested wheres to search for a user by multiple fields:

    $users_query->where('company_uuid', '=', $company_uuid);
    $users_query->where('is_active', '=', true);
    $users_query->whereNested(function($query) use ($search){
        /** @var Builder $query */
        $query
            ->where('first_name', 'like', '%' . $search . '%')
            ->orWhere('last_name', 'like', '%' . $search . '%')
            ->orWhere('email', 'like', '%' . $search . '%');
    });

Supposing you want to stack where layers without losing them on using orWhere Wouldn't this be the same thing ?

   $challenge = $this->challenges()
       ->where('open', true)
       ->whereNested(function($q) use ($user_id, $opponent_id) {
           $query->where('player_1', $user_id)
               ->where('player_2', $opponent_id);

           $query->orWhere('player_1', $opponent_id)
               ->where('player_2', $user_id);
   })->first();

You can use where then additional where and pass conditions as arrays. Between two where is 'And' operation. Inside the second where is 'Or' operation.

Example:

$users = DB::table('users')->where('status', 'value')->where([
    ['age', '>', '10'],
    ['subscribed', '<>', '1'],
])->get();