简体   繁体   English

Laravel hasOne 通过数据透视表

[英]Laravel hasOne through a pivot table

So I have 2 models, User & Profile, the relationship is set up as follows:所以我有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');
    }

I have 3 tables, users, profiles & user_profiles (the pivot table)我有 3 个表、用户、配置文件和 user_profiles(数据透视表)

I have a column in my users table called active_profile which gets populated with a profile id.我的用户表中有一个名为active_profile的列,其中填充了配置文件 ID。

How can I set up the relationship so that I can call something like the following:我如何建立关系,以便我可以调用以下内容:

$user->active_profile

So that it will return all the profile information for the id set in active_profile?以便它将返回active_profile中设置的id的所有配置文件信息?

On Laravel 5.8, since I wanted to use it with eager loading I used this package: https://github.com/staudenmeir/eloquent-has-many-deep在 Laravel 5.8 上,因为我想在预加载中使用它,所以我使用了这个包: https : //github.com/staudenmeir/eloquent-has-many-deep

This was my scenario这是我的场景
A user can be tagged on many photo and a photo can have many users tagged on.一个用户可以在许多照片上被标记,一张照片可以有许多用户被标记。 I wanted to have a relationship to get the latest photo the user has been tagged on.我想建立一个关系来获取用户被标记的最新照片。

I think my scenario can also be applied to any many-to-many relationship我认为我的场景也可以应用于任何多对多关系

I did the pivot model UserPhoto我做了枢轴模型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);
    }

}

And then on my User model using staudenmeir 's package:然后在我的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();
    }
}

Then I can easily do something like this:然后我可以轻松地做这样的事情:

User::with('latestPhoto')->get() and $user->latestPhoto User::with('latestPhoto')->get()$user->latestPhoto


Edit: In an another question, someone asked the same without using a package.编辑:在另一个问题中,有人在不使用包的情况下问了同样的问题。 I also provided an answer that will do the same result.我还提供了一个可以产生相同结果的答案

But after digging deeper, from both answers, you may avoid the n+1 query, you will still hydrate all the photos from your requested users.但是在深入挖掘之后,从这两个答案中,您可能会避免 n+1 查询,您仍然会从请求的用户那里获取所有照片。 I don't think it's possible to avoid one or the other approach.我认为不可能避免一种或另一种方法。 The cache could be an answer though.不过,缓存可能是一个答案。

I could be wrong but why not just use a belongsTo relationship?我可能是错的,但为什么不使用belongsTo关系呢?

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

Hope this helps!希望这可以帮助!

You can add a method into your User model like this :您可以将方法添加到您的User模型中,如下所示:

public function active_profile ()
{
   return $this->profiles()
          ->find($this->active_profile);
}

and then you can call the method as $user->active_profile();然后你可以调用该方法为 $user->active_profile();

You could add extra field in pivot table, for example active = enum(y, n) , then set unique key (user_id, active) and then use wherePivot method in user model:您可以在数据透视表中添加额外的字段,例如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');
}

It requires DB refactoring though.虽然它需要数据库重构。

您应该能够使用find获取资源

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM