在Laravel/Eloquent中,如何与';喜欢';或';不喜欢';地位

在Laravel/Eloquent中,如何与';喜欢';或';不喜欢';地位,laravel,eloquent,blade,relationships,Laravel,Eloquent,Blade,Relationships,这是我之前问的一个问题的延伸,这个问题是如何建立一个。用户可以创建多个想法。任何用户都可以“喜欢”或“不喜欢”任何想法 如前一篇文章所述,以下是我在拉雷维尔的关系: 用户 public function ideas(){ return $this->hasMany('Idea'); } public function liked(){ return $this->belongsToMany('Idea', 'ideas_likes')->withPivot('

这是我之前问的一个问题的延伸,这个问题是如何建立一个。用户可以创建多个想法。任何用户都可以“喜欢”或“不喜欢”任何想法

如前一篇文章所述,以下是我在拉雷维尔的关系:

用户

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
我有一个网页,列出了不同用户的想法。只有经过身份验证的用户才能访问此页面。每个想法旁边都有一个“喜欢”和“不喜欢”按钮。单击“喜欢”按钮时,将向ideas_likes表添加一个条目,“喜欢”布尔值设置为true。单击“不喜欢”按钮,添加条目时,“喜欢”boolen设置为false

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

在我的视图中显示这些想法时,我会像这样循环:

@foreach ($ideas as $idea)
  <div class="idea">
    <h1>{{ $idea->title }}</h1>
    <p>{{ $idea->description }}</p>
  </div>
@endforeach
这是返回所有想法的列表,以及它们相关的用户信息。然而,现在情况变得更加棘手了。我想要所有的想法,加上它们相关的用户信息(发布者),除了那些当前认证用户不喜欢的想法,如果认证用户喜欢,也要突出显示。呸


任何帮助都将不胜感激。

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

$ideas = Idea::with('user', 'likes')->whereDoesntHave('likes', function($q){
    $q->where('user_id', Auth::id());
    $q->where('liked', false);
})->get();
现在,您可以添加一个来创建一个动态的
属性。在
Idea
中:

public function getLikedAttribute(){
    $user = $this->likes->find(Auth::id());
    return $user != null && $user->pivot->liked == true;
}
你可以像在你的问题中那样使用它<代码>$idea->喜欢
。请注意,要使用此访问器,您应该立即加载
likes
。否则,当您访问
->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'];
}
public function getLikedAttribute(){
    return ! $this->likedByCurrentUser->isEmpty();
}
你看,回路不见了

最后,您需要加载新关系。下面是一个例子:

$ideas = Idea::with('user', 'likedByCurrentUser')->whereDoesntHave('likes', function($q){
    $q->where('user_id', Auth::id());
    $q->where('liked', false);
})->get();
或者,您可以向模型中带有数组的中添加像CurrentUser一样的
,以便随时加载该数组

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->first()['liked'];
}
public function getLikedAttribute(){
    return ! $this->likedByCurrentUser->isEmpty();
}

用法与上面相同。

使用
中删除
likes
并执行
$this->likes()->查找(Auth::id())在访问者中,因为看起来他不需要喜欢的东西?虽然这两种方法在性能上都不太好,不是吗?不,从那以后,每次访问
like
get时,它都会运行一个查询(这将在循环中完成…),但是
find()
对集合的速度有多快?我确信它比运行db查询快。但我同意这不是一个理想的解决方案。如果你有更好的想法,请告诉我。这比查询好得多,但仍然是一个问题。
public function getLikedAttribute(){
    return ! $this->likedByCurrentUser->isEmpty();
}