Since this is a Symfony2 bundle, we'll adapt it for Laravel using Laravel Symfony Bridge or Laravel Symfony Integration (e.g., spatie/laravel-symfony-support). Here’s how to start:
Install Dependencies
composer require baconmanager/acl-bundle
composer require symfony/console symfony/dependency-injection symfony/http-kernel
Register the Bundle
In config/app.php, add the bundle to the extra.bundles array:
'extra.bundles' => [
// ...
Bacon\Bundle\AclBundle\BaconAclBundle::class,
],
Configure ACL
In config/acl.php (create if missing):
return [
'user_class' => App\Models\User::class,
'group_class' => App\Models\Group::class,
'route_redirect_after_save' => 'fos_user_group_list',
'configuration' => [
'entities' => [
'module_class' => Bacon\Bundle\AclBundle\Entity\Module::class,
'module_actions' => App\Models\ModuleActions::class,
'module_actions_group' => App\Models\ModuleActionsGroup::class,
],
],
];
Define Routes
In routes/web.php:
Route::group(['prefix' => 'admin'], function () {
// FOSUser Group Routes
Route::resource('group', \FOS\UserBundle\Controller\GroupController::class)
->names('fos_user_group');
// ACL Module Routes
Route::resource('acl/module', \Bacon\Bundle\AclBundle\Controller\ModuleController::class)
->names('bacon_acl_module');
});
Create Required Entities
Adapt the provided Symfony entities to Laravel Eloquent models (e.g., User, Group, ModuleActions, ModuleActionsGroup). Example for ModuleActionsGroup:
namespace App\Models;
use Bacon\Bundle\AclBundle\Model\ModuleActionsGroupInterface;
use Bacon\Bundle\CoreBundle\Entity\BaseEntity;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class ModuleActionsGroup extends Model implements ModuleActionsGroupInterface
{
protected $table = 'module_actions_has_group';
public function group(): BelongsTo
{
return $this->belongsTo(Group::class, 'group_id');
}
public function module(): BelongsTo
{
return $this->belongsTo(\Bacon\Bundle\AclBundle\Entity\Module::class, 'module_id');
}
public function moduleActions(): BelongsTo
{
return $this->belongsTo(ModuleActions::class, 'module_actions_id');
}
}
Run Migrations
Generate and run migrations for the new tables (e.g., module_actions, module_actions_has_group).
First Use Case: Assign Permissions
Use the admin panel at /admin/acl/module to define modules (e.g., "Users", "Products") and their actions (e.g., "view", "edit"). Assign these to groups via /admin/group.
Define Modules/Actions:
Create Module entities (e.g., "Dashboard", "Orders") and associate them with ModuleActions (e.g., "create", "delete").
$module = new \Bacon\Bundle\AclBundle\Entity\Module();
$module->setName('Orders');
$module->setRoute('orders.index');
$module->save();
$action = new App\Models\ModuleActions();
$action->setModule($module);
$action->setName('delete');
$action->save();
Assign to Groups:
Link actions to groups via ModuleActionsGroup:
$group = App\Models\Group::find(1); // "Admins" group
$moduleActionsGroup = new App\Models\ModuleActionsGroup();
$moduleActionsGroup->setGroup($group);
$moduleActionsGroup->setModuleActions($action);
$moduleActionsGroup->setEnabled(true);
$moduleActionsGroup->save();
Check Permissions in Code: Use a service or repository to check if a user (via their groups) has access:
public function isAllowed($user, $moduleRoute, $action)
{
$groupIds = $user->groups->pluck('id');
return App\Models\ModuleActionsGroup::whereIn('group_id', $groupIds)
->where('module.route', $moduleRoute)
->where('module_actions.name', $action)
->where('enabled', true)
->exists();
}
Create a middleware to enforce ACL checks:
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class AclMiddleware
{
public function handle(Request $request, Closure $next)
{
$user = auth()->user();
$moduleRoute = $request->route()->getName();
$action = $request->method(); // e.g., "GET", "POST"
if (!$this->isAllowed($user, $moduleRoute, strtolower($action))) {
abort(403, 'Unauthorized action.');
}
return $next($request);
}
protected function isAllowed($user, $moduleRoute, $action)
{
// Implement logic from the previous example.
}
}
Register it in app/Http/Kernel.php:
protected $routeMiddleware = [
'acl' => \App\Http\Middleware\AclMiddleware::class,
];
Apply to routes:
Route::get('/admin/orders/{order}/delete', function () {
// ...
})->middleware('acl');
Use Blade directives to hide/show UI elements based on ACL:
@php
$canEdit = \App\Http\Middleware\AclMiddleware::isAllowed(
auth()->user(),
'orders.index',
'edit'
);
@endphp
@if($canEdit)
<button class="btn btn-edit">Edit</button>
@endif
For admin panels, fetch all permissions for a group:
$group = App\Models\Group::find(1);
$permissions = App\Models\ModuleActionsGroup::where('group_id', $group->id)
->with(['moduleActions', 'module'])
->get();
Render in a table with checkboxes for toggling enabled.
Laravel vs. Symfony ORM: The bundle assumes Doctrine ORM. For Laravel, ensure:
module_actions_has_group).belongsTo instead of @ORM\ManyToOne).module_id, group_id).Base Classes:
The bundle provides base classes (e.g., BaseModuleActions). Extend these in Laravel by copying their properties/methods to your Eloquent models.
route_redirect_after_save:
The config expects a Symfony route name (e.g., fos_user_group_list). In Laravel, use the route name defined in routes/web.php (e.g., group.index).
If redirects fail, debug with:
dd(Route::getRoutes()->getByName('fos_user_group_list')); // Check if route exists.
Admin Prefix:
The bundle assumes routes are prefixed with /admin/. Adjust the prefix in routing.yml (Laravel: routes/web.php) if needed.
public function isAllowed($user, $moduleRoute, $action)
{
$cacheKey = "acl:{$user->id}:{$moduleRoute}:{$action}";
return cache()->remember($cacheKey, now()->addHours(1), function () use ($user, $moduleRoute, $action) {
return App\Models\ModuleActionsGroup::whereIn('group_id', $user->groups->pluck('id'))
->where('module.route', $moduleRoute)
->where('module_actions.name', $action)
->where('enabled', true)
->exists();
});
}
if (!$this->isAllowed($user, $moduleRoute, $action)) {
\Log::debug("ACL Denied", [
'user_id' => $user->id,
'module_route' => $moduleRoute
How can I help you explore Laravel packages today?