When using Spatie in Laravel one can use the following statement to manually retrieve the permissions for a given role:
$rolePermissions = Permission::join("role_has_permissions","role_has_permissions.permission_id","=","permissions.id")
->where("role_has_permissions.role_id",$role_id)
->get();
I know the join
method is defined in Eloquent's Builder.php
file: vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php
However, the Permission
class (vendor/spatie/laravel-permission/src/Models/Permission.php
) does not define a join
method, and neither does the Model
class (vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php
) that is extended by Permission
. Meanwhile, the Model
class also does not include a join
method and does not extend any other classes, like for example the Builder
class.
So, how come that the Permission
class can invoque the join
method?
To answer your specific question of:
So, how come that the Permission class can invoque the join method?
You will probably find your answer here.
Model.php line# 2475 (if this is the correct version, I just checked github)
The reason it works is because if a method is not found in the instances scope (eg the method can not be called on the object) at call time then the magic methods __call or __callStatic are called. You can provide access to other instances through those methods allowing access to other objects and there methods etc. It's a common pattern known as overloading.
public static function __callStatic($method, $parameters)
{
if (static::isScopeMethodWithAttribute($method)) {
return static::query()->$method(...$parameters);
}
return (new static)->$method(...$parameters);
}
For more information on the topic see the manual.