Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Colin_Laws's avatar

Access Multiple Relationships On A Pivot Model Through A Model Using That Relationship

takes a deep breath yes, it's a lengthy title, I apologize!

I have a pivot table that joins three tables together: Users, Accounts, and Permissions.

The pivot table defines a user's access level to an account.

The individual permissions are not defined on the intermediate table because the permission table is related not only to the intermediate table between users and accounts, but also between another table that is irrelevant to this situation (I thought I would elaborate so that nobody would offer that as a solution).

What I need to do:

On the Account model, I define the relationship:


// ACCOUNT MODEL

public function users()
{
    return $this->belongsToMany('App\Models\Legacy\User', 'account_users', 'account_id', 'user_id')->withPivot('permission');

}

I want to add a method to the Account model that can filter the related users based on a property defined on the intermediate table's relationship to the permission table.

The permission table has a set of binary columns that dictate if a user is: an owner, billing admin, etc.

Something like this?


// ACCOUNT MODEL

public function owners()
{
    // The owner field exists on the permission table.
    // How do I access the pivot table's relationship to 
    // permissions right here?
    return users()->where('owner', true);
}

0 likes
1 reply
Colin_Laws's avatar
Colin_Laws
OP
Best Answer
Level 3

In order to pull relationships on a pivot table, you must create a custom pivot model.

The misunderstanding I was having was that the pivot property was already pulling a pivot model I created, whereas it turns out that in Eloquent, you create what is known as a CustomPivotModel.

In my App\Models namespace I have models for Account, User, and Permission objects.

In my App\Models\Pivot namespace, I created an AccountUserPermission class that extends Illuminate\Database\Eloquent\Relations\Pivot.


namespace App\Models\Pivots;

use Illuminate\Database\Eloquent\Relations\Pivot;

// Take note, we must extend the Pivot type!
class AccountUserPermission extends Pivot
{
    public function account()
    {
        return $this->belongsTo('App\Models\Account');
    }

    public function user()
    {
        return $this->belongsTo('App\Models\User', 'user_id', 'user_id');
    }

    public function permission()
    {
        return $this->belongsTo('App\Models\Permission');
    }
}

This is what I added to my User model in App\Models\User:


// You will of course have to add a use statement for 
// the types we will be referencing
use App\Models\Account;
use App\Models\Pivot\AccountUserPermission;
use Illuminate\Database\Eloquent\Relations\Pivot;

// Override the newPivot function on the User model
public function newPivot(Model $parent, array $attributes, $table, $exists, $using = null) 
{
    if ($parent instanceof Account) {
        return new AccountUserPermission($parent, $attributes, $table, $exists, $using);
    }

    return parent::newPivot($parent, $attributes, $table, $exists, $using);
}

The code on the other objects looks similar, we simply just override the newPivot function on models that will be using the custom pivot model.


// Account model (I'll shorten it up this time, it should practically
// look identical to the code above with the user model)

public function newPivot(Model $parent, array $attributes, $table, $exists, $using = null) 
{
    if ($parent instanceof User) {
        return new AccountUserPermission($parent, $attributes, $table, $exists, $using);
    }

    return parent::newPivot($parent, $attributes, $table, $exists, $using);
}

The solution was fairly easy. Now when I need to access that pivot table, if I have a user object, it looks like this:


// Pull an arbitrary user for this example
$user = App\Models\User::first();

// When we access the pivot property, it is calling our
// overridden newPivot method and returning an instance
// of AccountUserPermissions.

// Check if this user is an owner
if ($user->pivot->permission->owner)
{
    dd("Congratulations, you've won!");
}

3 likes

Please or to participate in this conversation.