php - Custom Laravel Relations?
Hypothetical situation: Let's say we have 3 models:
User
Role
Permission
Let's also sayUser
has a many-to-many relation withRole
, andRole
has a many-to-many relation withPermission
.
So their models might look something like this. (I kept them brief on purpose.)
class User
{
public function roles() {
return $this->belongsToMany(Role::class);
}
}
class Role
{
public function users() {
return $this->belongsToMany(User::class);
}
public function permissions() {
return $this->belongsToMany(Permission::class);
}
}
class Permission
{
public function roles() {
return $this->belongsToMany(Role::class);
}
}
What if you wanted to get all thePermission
s for aUser
? There isn't aBelongsToManyThrough
.
It seems as though you are sort of stuck doing something that doesn't feel quite right and doesn't work with things likeUser::with('permissions')
orUser::has('permissions')
.
class User
{
public function permissions() {
$permissions = [];
foreach ($this->roles as $role) {
foreach ($role->permissions as $permission) {
$permissions = array_merge($permissions, $permission);
}
}
return $permissions;
}
}
This example is, just one example, don't read too much into it. The point is, how can you define a custom relationship? Another example could be the relationship between a facebook comment and the author's mother. Weird, I know, but hopefully you get the idea. Custom Relationships. How?
In my mind, a good solution would be for that relationship to be described in a similar way to how describe any other relationship in Laravel. Something that returns an EloquentRelation
.
class User
{
public function permissions() {
return $this->customRelation(Permission::class, ...);
}
}
Does something like this already exist?
Answer
Solution:
The closest thing to a solution was what @biship posted in the comments. Where you would manually modify the properties of an existing
Relation
. This might work well in some scenarios. Really, it may be the right solution in some cases. However, I found I was having to strip down all of theconstraints
added by theRelation
and manually add any newconstraints
I needed.My thinking is this... If you're going to be stripping down the
constraints
each time so that theRelation
is just "bare". Why not make a customRelation
that doesn't add anyconstraints
itself and takes aClosure
to help facilitate addingconstraints
?Solution
Something like this seems to be working well for me. At least, this is the basic concept:
The methods not implemented yet are used for eager loading and must be declared as they are abstract. I haven't that far yet. :)
And a trait to make this new
Custom
Relation easier to use.Usage
Github
I went a ahead and put all this on Github just in case there are more people who are interested in something like this. This is still sort of a science experiment in my opinion. But, hey, we can figure this out together. :)
Answer
Solution:
Have you looked into the
hasManyThrough
relationship that Laravel offers?Laravel HasManyThrough
It should help you retrieve all the permissions for a user.
Answer
Solution:
I believe this concept already exists. You may choose on using Laravel ACL Roles and Permissions or Gate, or a package known as Entrust by zizaco.
Zizaco - Entrust
Laracast - watch video 13 and 14
Good luck!