在 Laravel / Eloquent 中,如何获取项目以及 'liked' 或 'disliked' 状态
In Laravel / Eloquent, how to fetch items along with 'liked' or 'disliked' status
这是对我之前提出的一个问题的扩展,该问题是如何设置 。一个用户可以创建多个想法。任何用户都可以 'like' 或 'dislike' 任何想法。
如前一篇文章所述,这是我在 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'table看起来像:
ideas_likes
------------
id primary key
user_id foreign key
idea_id foreign key
liked boolean
我有一个网页列出了来自不同用户的想法。只有经过身份验证的用户才能访问此页面。每个想法旁边都有一个 喜欢 和 不喜欢 按钮。单击 like 按钮时,将向 ideas_likes table 添加一个条目,并将 'liked' 布尔值设置为 true。单击 dislike 按钮时,添加条目时 'liked' boolen 设置为 false。
当用户 不喜欢 某个想法时,该想法不应再显示在该用户的列表中。如果用户 喜欢 一个想法,则该想法将在列表中突出显示。
在我的视图中展示想法时,我会像这样循环浏览它们:
@foreach ($ideas as $idea)
<div class="idea">
<h1>{{ $idea->title }}</h1>
<p>{{ $idea->description }}</p>
</div>
@endforeach
但是,如前所述,我想强调查看列表的用户 'liked' 提出的想法。也许它看起来像这样:
@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
在将 'likes' 的概念引入我的应用程序之前,我收集想法和用户信息的查询如下所示:
$ideas = Idea::with('user')->orderBy('created_at', 'desc')->get();
那是返回所有想法的列表,以及它们的相关用户信息。然而,现在它变得更加棘手。我想要所有的想法,加上它们相关的用户信息(无论是谁发布的),除了那些被当前经过身份验证的用户不喜欢的想法,并且还突出显示它们是否被经过身份验证的用户喜欢。呸!
如有任何帮助,我们将不胜感激。
这会处理预先加载并过滤掉当前用户不喜欢的想法。
$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->liked
。请注意,您应该预先加载 likes
才能使用此访问器。否则,对于每个想法,当您访问 ->liked
.
时,都会有一个额外的查询 运行 fetch 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();
}
用法同上。
这是对我之前提出的一个问题的扩展,该问题是如何设置
如前一篇文章所述,这是我在 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'table看起来像:
ideas_likes
------------
id primary key
user_id foreign key
idea_id foreign key
liked boolean
我有一个网页列出了来自不同用户的想法。只有经过身份验证的用户才能访问此页面。每个想法旁边都有一个 喜欢 和 不喜欢 按钮。单击 like 按钮时,将向 ideas_likes table 添加一个条目,并将 'liked' 布尔值设置为 true。单击 dislike 按钮时,添加条目时 'liked' boolen 设置为 false。
当用户 不喜欢 某个想法时,该想法不应再显示在该用户的列表中。如果用户 喜欢 一个想法,则该想法将在列表中突出显示。
在我的视图中展示想法时,我会像这样循环浏览它们:
@foreach ($ideas as $idea)
<div class="idea">
<h1>{{ $idea->title }}</h1>
<p>{{ $idea->description }}</p>
</div>
@endforeach
但是,如前所述,我想强调查看列表的用户 'liked' 提出的想法。也许它看起来像这样:
@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
在将 'likes' 的概念引入我的应用程序之前,我收集想法和用户信息的查询如下所示:
$ideas = Idea::with('user')->orderBy('created_at', 'desc')->get();
那是返回所有想法的列表,以及它们的相关用户信息。然而,现在它变得更加棘手。我想要所有的想法,加上它们相关的用户信息(无论是谁发布的),除了那些被当前经过身份验证的用户不喜欢的想法,并且还突出显示它们是否被经过身份验证的用户喜欢。呸!
如有任何帮助,我们将不胜感激。
这会处理预先加载并过滤掉当前用户不喜欢的想法。
$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->liked
。请注意,您应该预先加载 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'];
}
你看,循环消失了!
最后你需要预先加载新的关系。这是示例:
$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();
}
用法同上。