Laravel hasOne through a pivot table

隐身守侯 提交于 2020-01-24 09:05:51

问题


So I have 2 models, User & Profile, the relationship is set up as follows:

    /**
     * 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)

I have a column in my users table called active_profile which gets populated with a 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?


回答1:


You can add a method into your User model like this :

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

and then you can call the method as $user->active_profile();




回答2:


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

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

<?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:

<?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


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. I don't think it's possible to avoid one or the other approach. The cache could be an answer though.




回答3:


I could be wrong but why not just use a belongsTo relationship?

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

Hope this helps!




回答4:


You could add extra field in pivot table, for example active = enum(y, n), then set unique key (user_id, active) and then use wherePivotmethod in user model:

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.




回答5:


You should be able to grab the resource using find

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


来源:https://stackoverflow.com/questions/42033777/laravel-hasone-through-a-pivot-table

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!