Laravel hasOne 通过数据透视表

Posted

技术标签:

【中文标题】Laravel hasOne 通过数据透视表【英文标题】:Laravel hasOne through a pivot table 【发布时间】:2017-06-21 09:17:51 【问题描述】:

所以我有2个模型,User & Profile,关系设置如下:

    /**
     * User belongs to many Profile
     *
     * @return \Illuminate\Database\Eloquent\Relations\belongsToMany
     */
    public function profiles()
    
        return $this->belongsToMany('App\Models\Profile', 'user_profiles');
    

我有 3 个表,用户、配置文件和 user_profiles(数据透视表)

我的用户表中有一个名为active_profile 的列,其中填充了个人资料ID。

我怎样才能建立这种关系,以便我可以调用类似以下的东西:

$user->active_profile

这样它将返回active_profile中设置的id的所有配置文件信息?

【问题讨论】:

以下帖子是否回答了您的问题? 【参考方案1】:

在 Laravel 5.8 上,因为我想通过 eager loading 使用它,所以我使用了这个包: https://github.com/staudenmeir/eloquent-has-many-deep

这是我的场景 一个用户可以在许多照片上被标记,而一张照片可以有许多用户被标记。我想建立关系以获取用户被标记的最新照片。

我认为我的场景也可以应用于任何多对多关系

我做了枢轴模型UserPhoto

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Relations\Pivot;

class UserPhoto extends Pivot


    public function user()
    
        return $this->belongsTo(User::class);
    

    public function photo()
    
        return $this->belongsTo(Photo::class);
    


然后在我的 User 模型上使用 staudenmeir 的包:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Staudenmeir\EloquentHasManyDeep\HasRelationships;

class User extends Model

    use HasRelationships;

    public function photos()
    
        return $this->belongsToMany(Photo::class);
    

    public function latestPhoto()
    
        return $this->hasOneDeep(Photo::class, [UserPhoto::class])
            ->latest();
    

然后我可以轻松地做这样的事情:

User::with('latestPhoto')-&gt;get()$user-&gt;latestPhoto


编辑: 在另一个问题中,有人在不使用包的情况下提出了同样的问题。 我还提供了an answer,它会产生相同的结果。

但是在深入挖掘之后,从这两个答案中,您可能会避免 n+1 查询,您仍然会为您请求的用户的所有照片添加水分。我认为不可能避免一个或其他方法。缓存可能是一个答案。

【讨论】:

太棒了。谢谢!这可能是 lara echo 系统中最被低估的软件包。 什么是“hasOneDeep”?我没有找到任何东西。 @scott 这是我在答案顶部提到的包中添加的方法。请参阅:github.com/staudenmeir/eloquent-has-many-deep#hasonedeep【参考方案2】:

我可能错了,但为什么不直接使用belongsTo 关系?

public function active_profile()

    return $this->belongsTo('App\Models\Profile', 'active_profile');

希望这会有所帮助!

【讨论】:

【参考方案3】:

您可以像这样将方法添加到您的 User 模型中:

public function active_profile ()

   return $this->profiles()
          ->find($this->active_profile);

然后你可以调用该方法为 $user->active_profile();

【讨论】:

【参考方案4】:

你应该可以使用find获取资源

$user->profiles()->find($user->active_profile);

【讨论】:

虽然这可行,但我希望有一个更优雅的解决方案,最好使用雄辩的关系。我将暂时实施您的解决方案,但想暂时将这个问题留给其他选项。【参考方案5】:

您可以在数据透视表中添加额外的字段,例如active = enum(y, n),然后设置unique key (user_id, active),然后在用户模型中使用wherePivot方法:

public function profiles()

  return $this->belongsToMany('App\Models\Profile', 'user_profiles');


public function activeProfile()

  return $this->belongsToMany('App\Models\Profile', 'user_profiles')->wherePivot('active', 'y');

但它需要数据库重构。

【讨论】:

以上是关于Laravel hasOne 通过数据透视表的主要内容,如果未能解决你的问题,请参考以下文章

Excle数据透透视表如何删除数据透视表

如何通过laravel创建数据透视表

(Laravel)通过数据透视表的多态关系

Laravel如何通过数据透视表获取相关字段列表

Laravel 5 hasManyThrough 数据透视表

将数据添加到 Laravel 数据透视表