【问题标题】:Laravel Eloquent multiple wheres gives wrong resultsLaravel Eloquent 多个 wheres 给出了错误的结果
【发布时间】:2022-01-17 03:42:42
【问题描述】:

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

        $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 eloquent


    【解决方案1】:

    将您的 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 模型上的 Scope,以便您可以调用 Game::playerMatches($player)->where('result', 1)->get() 等。请参阅文档:

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

    我不会对此进行过多介绍,但定义编号列,如home_player_1、home_player_2 等通常被认为是不好的数据做法。您应该定义一个home_players 表或games_players,其中type 列用于home 或away 表,并以这种方式关联Game 和Players。

    【讨论】:

    • 谢谢,正如你所说,无论如何我都会改变我的数据库结构。
    【解决方案2】:

    查看 Laravel 文档中Logical Grouping 上的帖子。我认为基于此,您对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."

    【讨论】:

    • 谢谢@TimLewis 我更新了我的答案。
    【解决方案3】:

    需要修改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 下添加它们。

    【讨论】:

      猜你喜欢
      • 2021-05-28
      • 1970-01-01
      • 2019-12-06
      • 1970-01-01
      • 2020-06-02
      • 2018-10-10
      • 1970-01-01
      • 2019-12-01
      • 2019-12-02
      相关资源
      最近更新 更多