【问题标题】:How to get data from 3 models connected with Has-One and Have-Many relationship?如何从与 Has-One 和 Have-Many 关系相关的 3 个模型中获取数据?
【发布时间】:2015-03-01 13:02:34
【问题描述】:

我的项目中有一个友谊请求模块。其中使用了以下 3 个表:-

  1. 用户
  2. 用户配置文件
  3. 友谊

用户:- Id、slug、姓名、电子邮件、密码

UserProfile :- Id、user_slug、Profile_pic、DOB..等

友谊:-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');
}   

用户档案模型:-

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 关系方法而不使用连接来获取这些数据。我的意思是如何在一个查询中使用 HasOne 和 HasMany 关系获取数据。

非常感谢任何帮助或建议。

谢谢

【问题讨论】:

    标签: php mysql laravel orm eloquent


    【解决方案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());
    }
    

    【讨论】:

    • 感谢您的详细回答。我将尝试在我的应用程序中实现这个逻辑。脱帽致敬:)
    • 感谢您的帮助....它返回空值。 $user = Auth::user(); $user->load('pendingFriendsOfMine.profile', 'pendingFriendOf.profile'); $pendingFriends = $user->pendingFriends; foreach ($pendingFriends as $user) { var_dump($user->profile); }' Should I call $user->loadPendingFriends()`方法之前调用$pendingFriends = $user->pendingFriends;
    • pendingFriendsOfMine获取随机用户并检查他是否有profile。对于那些没有相关配置文件的用户,它应该返回null。顺便说一句,我修复了 FK 错别字。
    • 感谢您的帮助。我正在使用此代码:- $user = Auth::user(); $user->load('pendingFriendOf.Profile'); $friendshipRequests = $user->pendingFriendOf; 但是现在我如何获取发送友谊请求的用户的友谊 ID 和个人资料详细信息?
    • 1 你为什么需要那个友谊ID?它只是一个数据透视表。pendingFriendOf 是带有 pivot 对象的 User 模型的集合,因此您调用 ->pivot->id(但您需要在关系定义上使用 withPivot('id') 2 访问个人资料详细信息,就像在我的示例中一样。一切正常,因此请确保您没有搞砸。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-07
    相关资源
    最近更新 更多