我的项目中有一个友情请求模块。正在使用以下3个表: -
用户: - ID,slug,名称,电子邮件,密码
UserProfile: - ID,user_slug,Profile_pic,DOB..etc。
友谊: - ID,User_slug,Friend_slug,状态
关系: -
用户模型: -
public function Profile(){
return $this->hasOne('UserProfile','user_slug','slug')->first();
}
public function sentFriendshipRequests(){
return $this->hasMany('Friendship','user_slug','slug');
}
public function receivedFriendshipRequests(){
return $this->hasMany('Friendship','friend_slug','slug');
}
UserProfile模型: -
public function User(){
return $this->belongsTo('User','user_slug','slug');
}
友谊模式: -
public function receiver(){
return $this->belongsTo('User','friend_slug','slug');
}
public function sender(){
return $this->belongsTo('User','user_slug','slug');
}
目标: - 我想显示用户收到的待处理友情请求列表。
所需数据: - 所有友谊请求具有当前登录用户的待处理状态&姓名,Slug,友情请求发送者的Profile_pic。
我的方法: -
$friendship_requests= Auth::user()->receivedFriendshipRequests();
foreach($friendship_requests as $frnd_req)
{
$sender_user=User::where('slug',$frnd_req->user_slug());
}
是否有其他正确的方法可以使用Eloquent Relationship方法获取此数据,而无需使用join。我的意思是如何在一个查询中使用HasOne和HasMany关系获取数据。
非常感谢任何帮助或建议。
由于
答案 0 :(得分:1)
这是一种自引用多对多关系,因此您根本不需要这些hasMany
/ belongsTo
关系。
您只需将一个belongsToMany
用于自己的请求,另一个用于收到请求。
首先阅读:https://stackoverflow.com/a/25057320/784588
然后添加这些关系:
// pending requests of mine
function pendingFriendsOfMine()
{
return $this->belongsToMany('User', 'friendship', 'user_slug', 'friend_slug')
->wherePivot('accepted', '=', 0)
->withPivot('accepted');
}
// pending received requests
function pendingFriendOf()
{
return $this->belongsToMany('User', 'friendship', 'friend_slug', 'user_slug')
->wherePivot('accepted', '=', 0)
->withPivot('accepted');
}
// accessor allowing you call $user->friends
public function getPendingFriendsAttribute()
{
if ( ! array_key_exists('pendingFriends', $this->relations)) $this->loadPendingFriends();
return $this->getRelation('pendingFriends');
}
protected function loadPendingFriends()
{
if ( ! array_key_exists('pendingFriends', $this->relations))
{
$pending = $this->mergePendingFriends();
$this->setRelation('pendingFriends', $pending);
}
}
protected function mergePendingFriends()
{
return $this->pendingFriendsOfMine->merge($this->pendingFriendOf);
}
然后你只需使用嵌套关系加载它:
$user = Auth::user();
$user->load('pendingFriendsOfMine.profile', 'pendingFriendOf.profile');
// the above will execute 4 queries - 2 for requests, 2 for related profiles
$pendingFriends = $user->pendingFriends; // for all pending requests
// or
// $user->load('pendingFriendOf.profile'); // 2 queries in this case
// $pendingRequests = $user()->pendingFriendOf; // for received requests only
foreach ($pendingFriends as $user) {
$user->profile; // eager loaded profie model
}
此外,您的代码中存在一些错误:
// there can't be first() in the relation definition
// and it is not needed anyway
public function Profile(){
return $this->hasOne('UserProfile','user_slug','slug')->first();
}
// You never want to run this User::where() ...
// in a foreach loop, for it will result in n+1 queries issue
// You need eager loading instead.
foreach($friendship_requests as $frnd_req)
{
$sender_user=User::where('slug',$frnd_req->user_slug());
}