Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Authority Controller Laravel Package

efficiently/authority-controller

AuthorityController provides a Laravel controller trait for role- and ability-based authorization. It offers convenient methods to authorize actions, check permissions, and enforce access rules in controllers, integrating with the Authority package for centralized user authorization.

View on GitHub
Deep Wiki
Context7

Getting Started

Install via Composer (the package targets Laravel 4 through 5.3, so pin your Laravel version accordingly):

composer require efficiently/authority-controller

On Laravel 4.x/5.0–5.2 you must manually register Efficiently\AuthorityController\AuthorityControllerServiceProvider in config/app.php; 5.3 will still resolve it via the provider list — do not assume auto-discovery for 5.4+ (it does not exist yet in this era).

Publish the rules file and open it first — it is the heart of the package:

php artisan vendor:publish --provider="Efficiently\AuthorityController\AuthorityControllerServiceProvider"

That yields config/authority.php with three sections you'll spend most of your time in:

  • roles — closures that identify a user's role(s).
  • aliases — grouped action names ('modify' => ['create','edit','destroy']).
  • rules — the actual permission matrix, keyed by role, mapping actions to targets ('all', 'own', or a closure).

Your first useful use case is locking down an admin section in 10 minutes: define an admin role, add 'manage' => 'all' to its rules, then in a controller:

use Efficiently\AuthorityController\Controller;

class PostsController extends Controller
{
    public function edit($id)
    {
        $post = Post::findOrFail($id);
        $this->authorize('edit', $post);   // throws AccessDeniedException on failure
        return view('posts.edit', compact('post'));
    }
}

If the request hits the edit action as a non-owner non-admin, the controller short-circuits and the exception is rendered as a 403 by the package's handler.

Implementation Patterns

Controller-level authorization as the default. The idiomatic workflow is to extend the package's base controller and call authorizeResource() in the constructor so every action is implicitly guarded according to a naming convention (index, show, create, store, edit, update, destroy). Then individual actions only need to pass the resource:

public function __construct()
{
    $this->authorizeResource();   // wires up per-action rules
}

This mirrors Rails/CanCan and is the biggest day-to-day win — you stop forgetting the authorize call in one action out of eight.

Rules over conditionals. Resist the urge to write if ($user->isAdmin()) in controllers. Every check belongs in config/authority.php as a rule closure, so the policy is centralised and greppable:

'rules' => [
    'user' => [
        'edit'   => 'own',
        'delete' => function ($user, \$post) { return $post->isDraft(); },
    ],
],

Aliases for CRUD groups. Group create, update, destroy under manage (or modify) so rule files don't grow into a wall of repetitive entries. Alias resolution happens before rule matching, so always prefer the alias in can() / authorize() calls to keep semantics stable.

Expose permissions to Blade. Use the facade helpers for conditional UI:

@if (Authority::can('edit', $post))
    <a href="{{ route('posts.edit', $post) }}">Edit</a>
@endif

Never rely on view-level hiding as the actual security boundary — always pair with $this->authorize() server-side.

Form requests and non-controller services. When a FormRequest needs authorization, call Authority::authorize('update', $this->route('post')) from authorize(). Same call works in jobs, console commands, and API resources.

Multi-resource checks. authorize() and can() accept arrays/collections when a rule should evaluate on each item — handy for bulk actions like destroyMany.

Testing hooks. Swap the rules array in a test's config or use Authority::setUser($user) to drive the same policy matrix your app uses in production; assert 403 responses rather than duplicating permission logic.

Gotchas and Tips

  • This is a legacy package. Laravel 5.4 introduced Gate/Policies, which is the canonical answer for new projects. Use authority-controller only on an existing 4.x–5.3 codebase; do not mix it with Gate in the same app — the two authorizers will disagree and debugging becomes a nightmare.
  • Config cache bites hard. php artisan config:cache serialises config/authority.php, and any closures in that file become unserialisable on some PHP versions. Keep rule closures simple; re-run config:clear when debugging mysteriously failing rules.
  • Ownership is inferred. Rules like 'own' typically depend on a user_id (or similar) on the model — if your foreign key is named differently or nested (post.author_id), the rule silently fails. Explicitly write the comparison instead of relying on 'own' if your schema deviates.
  • The exception is not a standard Laravel 403. Efficiently\AuthorityController\Exceptions\AccessDeniedException needs to be caught in app/Exceptions/Handler.php (or rendered) if you want JSON responses for API routes — otherwise XHR clients get an HTML error page.
  • Guest users. The package resolves the current user via Auth::user(); anonymous visitors are null and will fail every check. Either force authentication before authorization or add a guest role in roles if you support anonymous read.
  • Performance. Rule closures run on every check — do not Post::find() inside a rule. Pass the already-loaded model in from the controller.
  • Constructor gotcha. authorizeResource() runs before $this->middleware() resolves. If you need route-model binding before the check, call $this->authorize(...) explicitly at the top of the action instead of relying on the constructor hook.
  • Debugging tips. When a check fails unexpectedly, temporarily log Authority::can('action', $resource), the resolved role list, and the raw rule key (role.action.target) — 90% of bugs are a rule not matching because of an unlisted alias or a role closure returning false due to a lazy-loaded relation.
  • Extension point. Custom resolvers (e.g. tenant-scoped roles) are cleanest by replacing the roles closure config rather than subclassing the controller — the role matrix is one of the few parts of the package that's safely overridable at the config layer.
  • Pin the version. Because the package is unmaintained relative to modern Laravel, lock the Composer constraint and plan a migration to Gates/Policies as a separate ticket — do not let composer update drag in an incompatible Laravel minor.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console