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

xoctopus's avatar

Access distant relation through a polymorphic many-to-many relation

I write this question because I have been trying for days to figure out how I can get the result I expect and I have not found a solution.

It happens that I have 4 tables, which are related by polymorphic many-to-many relationships and normal many-to-many relationships. I am trying to create in one of my models, a method to be able to access a relation through the polymorphic pivot table. Let me explain, I have the following models:

 1. User
 2. Teacher
 3. Role
 4. Permission

The structure of the models is as follows:

User

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    public function roles()
    {
        return $this->morphToMany(Role::class), 'model', 'model_has_role');
    }

    public function permissions()
    {
        return $this->morphToMany(Permission::class), 'model', 'model_has_permission');
    }
}

Teacher

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Teacher extends Model
{
    public function roles()
    {
        return $this->morphToMany(Role::class), 'model', 'model_has_role');
    }

    public function permissions()
    {
        return $this->morphToMany(Permission::class), 'model', 'model_has_permission');
    }
}

Role

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Role extends Model
{
    public function users()
    {
        return $this->morphedByMany(User::class, 'model', 'model_has_role');
    }

    public function teachers()
    {
        return $this->morphedByMany(Teacher::class, 'model', 'model_has_role');
    }

    public function permissions()
    {
        return $this->belongsToMany(Permission::class);
    }
}

Permission

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Permission extends Model
{
    public function users()
    {
        return $this->morphedByMany(User::class, 'model', 'model_has_permission');
    }

    public function teachers()
    {
        return $this->morphedByMany(Teacher::class, 'model', 'model_has_permission');
    }

    public function roles()
    {
        return $this->belongsToMany(Role::class);
    }
}

As you can see:

  1. A user or teacher can have multiple roles (many-to-many polymorphic)
  2. A user or teacher can have several permissions directly (many-to-many polymorphic)
  3. A Role can have multiple permissions (many-to-many normal)

Now my problem is the following: I am trying to create in each of the models: User and Teacher, a method that allows me to access the relationship between the model and the permissions through the roles.

I am not trying to access the permissions that the associated user has through the polymorphic relationship, but rather the permissions that belong to each of the roles that the user has associated with.

For example, suppose I have the following content in my tables:

Table: users

+----+--------+
| id | name   |
+----+--------+
|  1 | User 1 |
|  2 | User 2 |
|  3 | User 3 |
+----+--------+

Table: roles

+----+--------+-------------+---------------------+---------------------+
| id | name   | description | created_at          | updated_at          |
+----+--------+-------------+---------------------+---------------------+
|  1 | Role 1 | NULL        | 2021-07-29 03:28:03 | 2021-07-29 03:28:03 |
|  2 | Role 2 | NULL        | 2021-07-29 03:28:03 | 2021-07-29 03:28:03 |
|  3 | Role 3 | NULL        | 2021-07-29 03:28:03 | 2021-07-29 03:28:03 |
+----+--------+-------------+---------------------+---------------------+

Table: permissions

+----+--------------+-------------+---------------------+---------------------+
| id | name         | description | created_at          | updated_at          |
+----+--------------+-------------+---------------------+---------------------+
|  1 | Permission 1 | NULL        | 2021-07-29 03:28:03 | 2021-07-29 03:28:03 |
|  2 | Permission 2 | NULL        | 2021-07-29 03:28:03 | 2021-07-29 03:28:03 |
|  3 | Permission 3 | NULL        | 2021-07-29 03:28:03 | 2021-07-29 03:28:03 |
+----+--------------+-------------+---------------------+---------------------+

Pivot Table: permission_role

+----+---------+---------------+
| id | role_id | permission_id |
+----+---------+---------------+
|  1 |       1 |             2 |
+----+---------+---------------+

Table for polymorphic relation between model and roles: model_has_role

+-----------------+----------+---------+
| model_type      | model_id | role_id |
+-----------------+----------+---------+
| App\Models\User |        1 |       1 |
+-----------------+----------+---------+

Table for polymorphic relation between model and roles: model_has_permission

+-----------------+----------+---------------+
| model_type      | model_id | permission_id |
+-----------------+----------+---------------+
| App\Models\User |        1 |             1 |
+-----------------+----------+---------------+

As you can see:

  1. The user: User 1, is assigned the role: Role 1
  2. The role: Role 1, has the permission associated: Permission 2
  3. The user: User 1, has the Permission 1 permission directly associated usign the polymorphic relationship.

Excuse the redundancy but my question is: How can I create within the User or Teacher model a method to directly access the relationship between User or Teacher and the permissions that each one has through the assigned roles.

Thank you very much in advance.

0 likes
2 replies
xoctopus's avatar

@silencebringer Hello, thank you for answering my question. Based on that package and looking at a few others, I have made some adjustments to the project that I am doing trying to satisfy what my project really needs. Some time ago I tried to use it and unfortunately it did not comply with what I required.

One of the main problems I ran into was this: https://github.com/spatie/laravel-permission/issues/1692#event-4685939683

After testing several packages, I decided to simply implement the role and permissions system, after all it does not seem so difficult and so I adjust everything to what I really need :)

I don't know if there is any way to achieve what I am trying to do. As far as I understand, hasManyThrough relationships would not help me for this type of problem.

I would appreciate any help you can give me.

Please or to participate in this conversation.