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

Laravel Docblock Acl Laravel Package

tjgazel/laravel-docblock-acl

Laravel DocBlock ACL lets you define access control rules directly in PHP docblocks, keeping authorization next to your controller actions. Annotate methods with roles or permissions and the package enforces them automatically—less boilerplate, clearer, self-documenting code.

View on GitHub
Deep Wiki
Context7

Getting Started

This release targets Laravel 6 and 7, so before anything else confirm your app is on that generation — composer require will fail hard on Laravel 8+ because of the framework constraints, illuminate/support and the laravel/ui view assumptions.

Minimal path:

  1. Install the package and run its migrations (php artisan migrate). Expect at least a permissions table, a roles/groups table, and a polymorphic pivot linking users to permission groups.
  2. Publish config and views (vendor:publish) — the shipped views are written for laravel/ui + Bootstrap 4, so publish them if you intend to customise rather than writing your own UI.
  3. Seed the permission catalogue first. The package is only useful once permissions exist; register them in a seeder so they survive fresh deploys and are versioned in git.
  4. Assign a user to a group via the model relationship, then verify with the package's can-style check inside tinker before wiring anything into controllers.

First real use case: gate a route or Blade block behind a permission, not a role. @can('posts.edit') / $user->can('posts.edit') keeps your authorisation checks stable when group composition changes — that is the whole point of supporting multiple groups per user, so lean on permission-level checks from day one rather than role-name checks.

Look at the package's trait (usually applied to the User model) first — that is where the relationship names and the permission-checking API live, and it dictates everything downstream.

Implementation Patterns

Multiple groups per user. The headline of this release. A user can belong to several groups and inherits the union of their permissions. Model this explicitly in your tests: assert a user in editors + moderators can do both, and be explicit about whether a deny in one group overrides an allow in another (most of these packages are additive-only — no deny precedence — so verify before designing around it).

Authorisation at three layers.

  • Route middleware (->middleware('permission:posts.edit') or a policy that delegates to $user->can()).
  • Policies for anything with a model and a record — permissions answer "can this user type do this action", policies answer "on this record".
  • Blade @can for UI visibility only. Never let a hidden button be the security boundary.

Seeding as the source of truth. Keep permissions in a dedicated seeder or a config array the seeder iterates. On deploy, run the seeder idempotently (firstOrCreate) so renaming a permission in code produces a new row rather than a silent gap.

Cache the permission set per user. Permission checks appear in loops, policies, and Blade partials. Resolve the user's effective permission list once per request (or per user with a short TTL cache) and answer checks from memory. Invalidate on group attach/detach/permission-edit — that invalidation is where bugs live, so centralise it in model events or an observer rather than sprinkling Cache::forget in controllers. Be aware that most permission packages ship their own cache layer; check whether it is already on before adding a second.

Livewire Full-Page Components. With Route::get('/admin', AdminDashboard::class), route middleware still runs, but anything rendered client-side after the initial mount is only as safe as the server-side checks inside the component. Put the can() check in mount() and re-check in every action method — a full-page component's actions are separate requests and do not re-run mount(). Component authors often forget this.

Views with laravel/ui + Bootstrap 4. Treat the shipped views as scaffolding you will replace. If your app is on Tailwind, don't fight the markup — publish the views, strip the Bootstrap classes, and keep only the form/route structure. The controllers and validation behind them are the reusable part.

Group management UI. A simple pivot-sync form ($user->groups()->sync($request->groups)) with a multi-select is usually enough; resist building a matrix editor until someone actually asks.

Gotchas and Tips

  • Laravel 6 and 7 are end-of-life. Laravel 6 security support ended September 2022, Laravel 7 has been unsupported since March 2021 (Laravel 7's PHP floor is 7.2.5). If this package is a dependency of a live app, the app itself is the risk — plan the framework upgrade and check whether a newer major of this package exists before committing. A v2.0.1 patch release that only adds Laravel 6/7 compatibility is a maintenance release, not a modernisation.
  • laravel/ui is legacy scaffolding. Laravel dropped it from the default install in 8.x in favour of Breeze/Jetstream. If you're on Laravel 7 the package's auth views will drop in cleanly; on anything newer they won't, and laravel/ui will fight your existing frontend.
  • Bootstrap 4 vs 5. Laravel 9+ ships Bootstrap 5 in laravel/ui 4.x. If you later upgrade the frontend, the v4 markup here (.form-group, .custom-select, .input-group-append) will break. Budget a markup pass, not just a CSS swap.
  • No negative permissions. Confirm whether a group can revoke a permission granted by another group. If checks are additive-only, don't design a "suspended moderators" group and assume it subtracts — use a dedicated check instead.
  • N+1 on group loading. Permission checks that lazy-load groups per call will hammer the database inside a table render. Eager load (with('groups.permissions')) on the user object used for the page, or rely on caching.
  • Cache staleness after sync(). The classic symptom: a user gains a permission in the admin UI but the change only appears after the next request, or worse, after a queue worker restart. Confirm the package's cache key includes the user id and that attach/detach events flush it; add your own observer if not.
  • Livewire hydration. If a component property holds a collection of groups and you render checkboxes from it, mutating the array doesn't persist until sync() runs in an action — and a stale property will happily re-save an outdated permission set. Re-read the user inside the action before syncing.
  • Permission naming drift. Use a resource.action convention (posts.edit, users.delete) and a constant list or enum in PHP that both the seeder and your checks reference. Free-typed strings are the most common source of "it says I can't, but I'm in the group" bugs.
  • Migrations on fresh installs. These packages often ship migrations that assume a particular table prefix or an existing users table. Check the migration order and publish/timestamp them before running migrate:fresh in CI.
  • Test the composition, not the package. Write a feature test that a multi-group user gets the expected union of permissions and that a non-member is rejected at the route level — that catches both package misconfiguration and accidental middleware removal during refactors.
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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin