【问题标题】:In Laravel / Eloquent, how to fetch items along with 'liked' or 'disliked' status在 Laravel / Eloquent 中,如何获取项目以及“喜欢”或“不喜欢”状态
【发布时间】:2015-03-01 04:39:27
【问题描述】:

这是对我之前提出的问题的扩展,即如何设置relationship between users, ideas, and 'likes'。一个用户可以创建多个想法。任何用户都可以“喜欢”或“不喜欢”任何想法。

如前文所述,以下是我在 Laravel 中的关系:

用户

public function ideas(){
    return $this->hasMany('Idea');
}

public function liked(){
    return $this->belongsToMany('Idea', 'ideas_likes')->withPivot('liked');
}

想法

public function likes(){
    return $this->belongsToMany('User', 'ideas_likes')->withPivot('liked');
}

public function user(){
    return $this->belongsTo('User');
}

我的“ideas_likes”表如下所示:

ideas_likes
------------
id        primary key
user_id   foreign key
idea_id   foreign key
liked     boolean

我有一个网页,其中列出了来自不同用户的想法。只有经过身份验证的用户才能访问此页面。每个想法旁边都有一个 likedislike 按钮。当点击 like 按钮时,会将一个条目添加到 idea_likes 表中,并将“liked”布尔值设置为 true。当点击 dislike 按钮时,会添加条目并将“liked”布尔值设置为 false。

当用户不喜欢某个想法时,该想法不应再出现在该用户的列表中。如果用户喜欢一个想法,那么该想法将在列表中突出显示。

当在我的视图中显示这些想法时,我将像这样循环它们:

@foreach ($ideas as $idea)
  <div class="idea">
    <h1>{{ $idea->title }}</h1>
    <p>{{ $idea->description }}</p>
  </div>
@endforeach

但是,如前所述,我想突出显示已被查看列表的用户“点赞”的想法。也许它看起来像这样:

@foreach ($ideas as $idea)
  <div class="idea@if($idea->liked) highlight@endif">
    <h1>{{ $idea->title }}</h1>
    <p>{{ $idea->description }}</p>
  </div>
@endforeach

另外,我还希望显示创意作者的用户名(不一定与登录用户相同):

@foreach ($ideas as $idea)
  <div class="idea@if($idea->liked) highlight@endif">
    <h1>{{ $idea->title }}</h1>
    <p>{{ $idea->description }}</p>
    <p>{{ $idea->user->username }}</p> <=== SOMETHING LIKE THIS
  </div>
@endforeach

在我的应用程序中引入“喜欢”的概念之前,我收集想法和用户信息的查询如下所示:

$ideas = Idea::with('user')->orderBy('created_at', 'desc')->get();

这是返回所有想法的列表,以及相关的用户信息。然而,现在它变得更加棘手。我想要所有的想法,加上他们相关的用户信息(无论是谁发布的),除了那些被当前认证用户不喜欢的想法,如果他们被认证用户喜欢,也会突出显示。呸!

任何帮助将不胜感激。

【问题讨论】:

    标签: laravel eloquent blade relationships


    【解决方案1】:

    这会处理急切加载并过滤掉当前用户不喜欢的想法。

    $ideas = Idea::with('user', 'likes')->whereDoesntHave('likes', function($q){
        $q->where('user_id', Auth::id());
        $q->where('liked', false);
    })->get();
    

    现在您可以添加accessor 来创建动态liked 属性。在Idea

    public function getLikedAttribute(){
        $user = $this->likes->find(Auth::id());
        return $user != null && $user->pivot->liked == true;
    }
    

    您可以像在问题中使用它一样使用它。 $idea-&gt;liked。请注意,您应该立即加载 likes 以使用此访问器。否则,当您访问 -&gt;liked 时,将针对每个想法运行额外的查询以获取 likes

    更新:更高效

    我找到了一种方法让它更高效,并且每个想法都没有循环。不过我觉得有点丑。为了能够预先加载数据,我必须创建一个新关系。

    public function likedByCurrentUser(){
        return $this->belongsToMany('User', 'ideas_likes')
                    ->where('user_id', Auth::id())
                    ->where('liked', true)
                    ->selectRaw('COUNT(*) > 0 AS liked');
    }
    

    这是重写的访问器:

    public function getLikedAttribute(){
        return !! $this->likedByCurrentUser->first()['liked'];
    }
    

    你看,循环消失了!

    最后,您需要预先加载新关系。示例如下:

    $ideas = Idea::with('user', 'likedByCurrentUser')->whereDoesntHave('likes', function($q){
        $q->where('user_id', Auth::id());
        $q->where('liked', false);
    })->get();
    

    或者,您可以将likedByCurrentUser 添加到模型中的with 数组中,这样它就会一直被预先加载。

    protected $with = array('likedByCurrentUser');
    

    更新 2

    现在看看我的旧解决方案,我相信这可以做得更好(希望它也能正常工作)

    关系:

    public function likedByCurrentUser(){
        return $this->belongsToMany('User', 'ideas_likes')
                    ->where('user_id', Auth::id())
                    ->where('liked', true);
    }
    

    访问者:

    public function getLikedAttribute(){
        return ! $this->likedByCurrentUser->isEmpty();
    }
    

    用法同上。

    【讨论】:

    • with 中删除likes 并在访问器中执行$this-&gt;likes()-&gt;find(Auth::id()); 不是更好吗,因为看起来他不需要喜欢?尽管两者的性能似乎都不太好,不是吗?
    • 没有,从那以后每次liked get 被访问时它都会运行一个查询(这将在一个循环中完成......)
    • 但是find() 在集合上的速度有多快?
    • 我确信它比运行数据库查询要快。但我同意这不是一个理想的解决方案。如果您有更好的主意,请告诉我
    • 是的,它肯定比查询好,但它仍然是loop per idea
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-06
    • 1970-01-01
    • 2013-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多