Overview
The GatePlugin automatically discovers and registers authorization policies for your module’s Eloquent models. It follows Laravel’s policy naming conventions to match models with their corresponding policy classes.
How It Works
The plugin scans your module’s Models directory and attempts to locate corresponding policy classes using Laravel’s standard naming conventions.
Discovery Process
- Find Models: Scans the module’s model files
- Locate Policies: For each model, searches for policies in two locations:
- Same nested structure:
Policies\Foo\BarPolicy for Models\Foo\Bar
- Flat structure:
Policies\BarPolicy for Models\Foo\Bar
- Register: Registers the policy with Laravel’s Gate
Source Code
public function discover(FinderFactory $finders): iterable
{
return $finders
->modelFileFinder()
->withModuleInfo()
->values()
->map(function(ModuleFileInfo $file) {
$fqcn = $file->fullyQualifiedClassName();
$namespace = rtrim($file->module()->namespaces->first(), '\\');
$candidates = [
$namespace.'\\Policies\\'.Str::after($fqcn, 'Models\\').'Policy',
$namespace.'\\Policies\\'.Str::afterLast($fqcn, '\\').'Policy',
];
foreach ($candidates as $candidate) {
if (class_exists($candidate)) {
return [
'fqcn' => $fqcn,
'policy' => $candidate,
];
}
}
return null;
})
->filter();
}
Expected Module Structure
app-modules/
blog/
src/
Models/
Post.php # Modules\Blog\Models\Post
Comment.php # Modules\Blog\Models\Comment
Policies/
PostPolicy.php # Modules\Blog\Policies\PostPolicy
CommentPolicy.php # Modules\Blog\Policies\CommentPolicy
Nested Models
For nested models, the plugin checks both patterns:
app-modules/
blog/
src/
Models/
Admin/
User.php # Modules\Blog\Models\Admin\User
Policies/
Admin/
UserPolicy.php # Option 1: Nested policy
UserPolicy.php # Option 2: Flat policy
Activation
The plugin uses the AfterResolving attribute to activate after Laravel’s Gate is resolved:
#[AfterResolving(Gate::class, parameter: 'gate')]
class GatePlugin extends Plugin
{
public function __construct(
protected Gate $gate
) {
}
}
Policy Registration
Policies are registered with Laravel’s Gate during the handling phase:
public function handle(Collection $data): void
{
$data->each(fn(array $row) => $this->gate->policy($row['fqcn'], $row['policy']));
}
Usage Example
Once policies are registered, use them like any Laravel policy:
use Modules\Blog\Models\Post;
// In a controller
public function update(Post $post)
{
$this->authorize('update', $post);
// Update the post...
}
// In Blade
@can('update', $post)
<a href="{{ route('posts.edit', $post) }}">Edit</a>
@endcan
// Using the Gate facade
if (Gate::allows('update', $post)) {
// User can update the post
}
Policy Class Example
<?php
namespace Modules\Blog\Policies;
use App\Models\User;
use Modules\Blog\Models\Post;
class PostPolicy
{
public function update(User $user, Post $post): bool
{
return $user->id === $post->user_id;
}
public function delete(User $user, Post $post): bool
{
return $user->id === $post->user_id;
}
}
The GatePlugin follows Laravel’s standard policy auto-discovery conventions, making authorization seamless across your modular application.
See Also