Laravel Eloquent 多个 wheres 给出了错误的结果

Laravel Eloquent multiple wheres gives wrong results

为什么下面这段代码返回错误结果?

        $player->wins = Game::where('home_player_1', '=', $player->id)
                            ->orWhere('home_player_2', '=', $player->id)
                            ->orWhere('home_player_3', '=', $player->id)
                            ->orWhere('home_player_4', '=', $player->id)
                            ->where('result', '=','1') // 1 = win
                            ->get();

        $player->losses = Game::where('home_player_1', '=', $player->id)
                            ->orWhere('home_player_2', '=', $player->id)
                            ->orWhere('home_player_3', '=', $player->id)
                            ->orWhere('home_player_4', '=', $player->id)
                            ->where('result', '=','0') // 0 = lose
                            ->get();

        $player->matches = Game::where('home_player_1', '=', $player->id)
                            ->orWhere('home_player_2', '=', $player->id)
                            ->orWhere('home_player_3', '=', $player->id)
                            ->orWhere('home_player_4', '=', $player->id)
                            ->get();

我得到的是 5 场比赛/5 胜/5 负,而实际上是 5/5/0。我应该怎么做?

查看 Laravel 文档中关于 Logical Grouping 的 post。我认为基于此,您对 matches 的陈述应该是:

$player->matches = Game::where(function ($query) use ($player) {
    $query->where('home_player_1', '=', $player->id)
          ->orWhere('home_player_2', '=', $player->id)
          ->orWhere('home_player_3', '=', $player->id)
          ->orWhere('home_player_4', '=', $player->id);
})->get();

我不确定这是否有帮助,因为我没有其余的代码,但请测试它并告诉我。

同样来自文档: "In fact, you should generally always group calls to the orWhere method in parentheses in order to avoid unexpected query behavior."

将您的 home_player_x 子句移动到 嵌套的 where 条件子句中:

$player->wins = Game::where(function ($query) use ($player) {
  return $query->where('home_player_1', $player->id)
  ->orWhere('home_player_2', $player->id)
  ->orWhere('home_player_3', $player->id)
  ->orWhere('home_player_4', $player->id);
})->where('result', 1)
->get();

...

这样,它就不会与最后一个 ->where('result') 子句冲突。

此外,由于您多次重复使用此子句,请将其定义为变量并重复使用:

$conditional = function ($query) use ($player) {
  return $query->where(function ($subQuery) use ($player) {
    return $subQuery->orWhere('home_player_1', $player->id)
    ->orWhere('home_player_2', $player->id)
    ->orWhere('home_player_3', $player->id)
    ->orWhere('home_player_4', $player->id);
  })
});

$player->wins = Game::where($conditional)->where('result', 1)->get();
$player->losses = Game::where($conditional)->where('result', 0)->get();
$player->matches = Game::where($conditional)->get();

或者,考虑将其定义为 Game 模型上的作用域,这样您就可以调用 Game::playerMatches($player)->where('result', 1)->get(),等等。请参阅相关文档:

https://laravel.com/docs/8.x/eloquent#local-scopes

我不会对此过多提及,但定义编号列,如 home_player_1home_player_2 等通常被认为是不良数据实践。您应该定义 home_players table 或 games_players,并为 homeaway table 定义一个 type 列并关联 GamePlayers 这样。

需要修改 orWhere() 条件,而不是上面你可以使用下面的 where 子句:

$player->wins = Game::where('result', '=','1') // 1 = win
    ->where(function ($query) use ($player) {
        $query->where('home_player_1', '=', $player->id)
            ->orWhere('home_player_2', '=', $player->id)
            ->orWhere('home_player_3', '=', $player->id)
            ->orWhere('home_player_4', '=', $player->id);
    })->get();

$player->losses = Game::where('result', '=', '0') // 0 = lose
    ->where(function ($query) use ($player) {
        $query->where('home_player_1', '=', $player->id)
            ->orWhere('home_player_2', '=', $player->id)
            ->orWhere('home_player_3', '=', $player->id)
            ->orWhere('home_player_4', '=', $player->id);
    })->get();


$player->matches = Game::
    where(function ($query) use ($player) {
        $query->where('home_player_1', '=', $player->id)
            ->orWhere('home_player_2', '=', $player->id)
            ->orWhere('home_player_3', '=', $player->id)
            ->orWhere('home_player_4', '=', $player->id);
    })->get();

当有多个orWhere()时,正常情况下不行,需要在单个where下添加。