【问题标题】:Efficiently find if user is present in many-to-many relationship in Laravel有效地查找用户是否存在于 Laravel 中的多对多关系中
【发布时间】:2021-08-10 16:33:03
【问题描述】:

用户可以关注游戏,游戏也有关注者。这是一个简单的多对多关联。

在呈现游戏列表时,我需要确定经过身份验证的用户是否在该特定迭代中关注游戏。像这样:

$games = App\Game::with('users')->all();

foreach($games as $game) {
    echo $game->title;
    echo $game->is_auth_user_following; // bool
}

所以在我的游戏模型中我有这个访问器:

// App\Game
public function getIsAuthUserFollowingAttribute()
{
    if (!Auth::id()) {
        return false;
    }

    return $this->users()->where('users.id', Auth::id())->exists();
}

这很好用,但是,在分析 Eloquent 执行的查询时,我看到它为循环中的每个游戏运行单独的查询。如果循环有 50 场比赛,那么我会得到 50 个如下所示的查询:

select exists(select * from `users`
                       inner join `game_user`
                           on `users`.`id` = `game_user`.`user_id`
                       where `game_user`.`game_id` = ?
                         and `users`.`id` = ?
                         and `users`.`deleted_at` is null) as `exists`
--- this 50 times...

问题:有没有办法在 Eloquent 中对此进行优化,以减少对数据透视表的查询次数?

【问题讨论】:

    标签: mysql laravel eloquent


    【解决方案1】:

    如果您正在使用此代码

    $games = App\Game::with('users')->all();
    

    然后您可以通过这种方式更改访问器。它不会做任何查询

    public function getIsAuthUserFollowingAttribute()
    {
        if (!Auth::id()) {
            return false;
        }
    
        return $this->users->where('id', Auth::id())->isNotEmpty();
    }
    

    更优化的代码是

    $games = App\Game::with('users:id')->all();
    

    【讨论】:

    • 工作就像一个魅力! Laravel 的有趣之处在于这些奇怪的事情如何产生巨大的影响。我从来没有想过尝试这种语法。
    猜你喜欢
    • 2018-06-25
    • 2014-05-28
    • 1970-01-01
    • 1970-01-01
    • 2021-07-02
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多