web-dev-qa-db-fra.com

Requête 'AND OR' imbriquée dans Eloquent

J'essaie actuellement de créer une requête imbriquée, comme suit:

public function getChallenge($user_id, $opponent_id)
{
    $challenge = $this->challenges()
            ->where('open', true)
            ->where(function($query) use ($user_id, $opponent_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();

    return $challenge;
}

Cela crée la requête suivante par exemple:

select * from `site_challenges_leagues` 
where `site_challenges_leagues`.`league_id` = '1' 
and `open` = '1'
and (`player_1` = '3' and `player_2` = '1') 
or (`player_1` = '1' and `player_2` = '3') 
limit 1

Cependant, cela renvoie toujours la première valeur de la table (où open est soit 1 ou 0), ce qui est incorrect. Pour que la requête soit correcte, elle doit contenir les deux ensembles de requêtes AND entre crochets, comme suit:

 select * from `site_challenges_leagues` 
 where `site_challenges_leagues`.`league_id` = '1' 
 and `open` = TRUE 

 and ((`player_1` = '3' and `player_2` = '1') 
 or (`player_1` = '1' and `player_2` = '3'))

 limit 1

Est-il possible de faire cela à Laravel? J'ai tenté de le faire; cependant, il a échoué:

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

    return $challenge;
}

Toute aide est grandement appréciée.

24
Kevin

Vous étiez très proche de la réponse

$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();

Ici sont les différences entre deux codes

38
Razor

J'avais besoin des endroits imbriqués pour rechercher un utilisateur par plusieurs champs:

    $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 . '%');
    });

Supposons que vous souhaitiez empiler where couches sans les perdre en utilisant orWhere Ne serait-ce pas la même chose?

   $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();
0
Gabi Dj