[Solved] Access distant relation through a polymorphic many-to-many relation

leo95batista Asks: 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:

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

The structure of the models is as follows:

User

Code:
<?php

namespace AppModels;

use IlluminateDatabaseEloquentModel;

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

Code:
<?php

namespace AppModels;

use IlluminateDatabaseEloquentModel;

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

Code:
<?php

namespace AppModels;

use IlluminateDatabaseEloquentModel;

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

Code:
<?php

namespace AppModels;

use IlluminateDatabaseEloquentModel;

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

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

Table: roles

Code:
+----+--------+-------------+---------------------+---------------------+
| 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

Code:
+----+--------------+-------------+---------------------+---------------------+
| 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

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

Table for polymorphic relation between model and roles: model_has_role

Code:
+-----------------+----------+---------+
| model_type      | model_id | role_id |
+-----------------+----------+---------+
| AppModelsUser |        1 |       1 |
+-----------------+----------+---------+

Table for polymorphic relation between model and roles: model_has_permission

Code:
+-----------------+----------+---------------+
| model_type      | model_id | permission_id |
+-----------------+----------+---------------+
| AppModelsUser |        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.

Ten-tools.com may not be responsible for the answers or solutions given to any question asked by the users. All Answers or responses are user generated answers and we do not have proof of its validity or correctness. Please vote for the answer that helped you in order to help others find out which is the most helpful answer. Questions labeled as solved may be solved or may not be solved depending on the type of question and the date posted for some posts may be scheduled to be deleted periodically. Do not hesitate to share your response here to help other visitors like you. Thank you, Ten-tools.