😆Use package lavary/laravel-menu create menu have role & permission (ok)
https://github.com/lavary/laravel-menu
Last updated
https://github.com/lavary/laravel-menu
Last updated
C:\xampp82\htdocs\lva2\app\Http\Middleware\GenerateMenus.php
<?php
namespace App\Http\Middleware;
use Closure;
class GenerateMenus
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @return mixed
*/
public function handle($request, Closure $next)
{
\Menu::make('admin_sidebar', function ($menu) {
// Dashboard
$menu->add('<i class="nav-icon fa-solid fa-cubes"></i> ' . __('Dashboard'), [
'route' => 'home',
'class' => 'nav-item',
])
->data([
'order' => 1,
'activematches' => 'admin/dashboard*',
])
->link->attr([
'class' => 'nav-link',
]);
// Notifications
$menu->add('<i class="nav-icon fas fa-bell"></i> Notifications', [
'route' => 'home',
'class' => 'nav-item',
])
->data([
'order' => 99,
'activematches' => 'admin/notifications*',
'permission' => [],
])
->link->attr([
'class' => 'nav-link',
]);
// Separator: Access Management
$menu->add('Management', [
'class' => 'nav-title',
])
->data([
'order' => 101,
'permission' => ['edit_settings', 'view_backups', 'view_users', 'view_roles', 'view_logs'],
]);
// Settings
$menu->add('<i class="nav-icon fas fa-cogs"></i> Settings', [
'route' => 'home',
'class' => 'nav-item',
])
->data([
'order' => 102,
'activematches' => 'admin/settings*',
'permission' => ['edit_settings'],
])
->link->attr([
'class' => 'nav-link',
]);
// Backup
$menu->add('<i class="nav-icon fas fa-archive"></i> Backups', [
'route' => 'home',
'class' => 'nav-item',
])
->data([
'order' => 103,
'activematches' => 'admin/backups*',
'permission' => ['view_backups'],
])
->link->attr([
'class' => 'nav-link',
]);
// Access Control Dropdown
$accessControl = $menu->add('<i class="nav-icon fa-solid fa-user-gear"></i> Access Control', [
'class' => 'nav-group',
])
->data([
'order' => 104,
'activematches' => [
'admin/users*',
'admin/roles*',
],
'permission' => ['view_users', 'view_roles'],
]);
$accessControl->link->attr([
'class' => 'nav-link nav-group-toggle',
'href' => '#',
]);
// Submenu: Users
$accessControl->add('<i class="nav-icon fa-solid fa-user-group"></i> Users', [
'route' => 'home',
'class' => 'nav-item',
])
->data([
'order' => 105,
'activematches' => 'admin/users*',
'permission' => ['view_users'],
])
->link->attr([
'class' => 'nav-link',
]);
// Submenu: Roles
$accessControl->add('<i class="nav-icon fa-solid fa-user-shield"></i> Roles', [
'route' => 'home',
'class' => 'nav-item',
])
->data([
'order' => 106,
'activematches' => 'admin/roles*',
'permission' => ['view_roles'],
])
->link->attr([
'class' => 'nav-link',
]);
// Log Viewer
// Log Viewer Dropdown
$accessControl = $menu->add('<i class="nav-icon fa-solid fa-list-check"></i> Log Viewer', [
'class' => 'nav-group',
])
->data([
'order' => 107,
'activematches' => [
'log-viewer*',
],
'permission' => ['view_logs'],
]);
$accessControl->link->attr([
'class' => 'nav-link nav-group-toggle',
'href' => '#',
]);
// Submenu: Log Viewer Dashboard
$accessControl->add('<i class="nav-icon fa-solid fa-list"></i> Dashboard', [
'route' => 'home',
'class' => 'nav-item',
])
->data([
'order' => 108,
'activematches' => 'admin/log-viewer',
])
->link->attr([
'class' => 'nav-link',
]);
// Submenu: Log Viewer Logs by Days
$accessControl->add('<i class="nav-icon fa-solid fa-list-ol"></i> Logs by Days', [
'route' => 'home',
'class' => 'nav-item',
])
->data([
'order' => 109,
'activematches' => 'admin/log-viewer/logs*',
])
->link->attr([
'class' => 'nav-link',
]);
// Access Permission Check
$menu->filter(function ($item) {
if ($item->data('permission')) {
if (auth()->check()) {
if (auth()->user()->hasRole('super admin')) {
return true;
} elseif (auth()->user()->hasAnyPermission($item->data('permission'))) {
return true;
}
}
return false;
} else {
return true;
}
});
// Set Active Menu
$menu->filter(function ($item) {
if ($item->activematches) {
$activematches = (is_string($item->activematches)) ? [$item->activematches] : $item->activematches;
foreach ($activematches as $pattern) {
if (request()->is($pattern)) {
$item->active();
$item->link->active();
if ($item->hasParent()) {
$item->parent()->active();
}
}
}
}
return true;
});
})->sortBy('order');
return $next($request);
}
}
C:\xampp82\htdocs\lva2\resources\views\welcome.blade.php
{!! $admin_sidebar->asUl( ['class' => 'sidebar-nav', 'data-coreui'=>'navigation', 'data-simplebar'], ['class' => 'nav-group-items'] ) !!}
C:\xampp82\htdocs\lva2\app\Http\Kernel.php
\App\Http\Middleware\GenerateMenus::class,
C:\xampp82\htdocs\lva2\config\app.php
Lavary\Menu\ServiceProvider::class,
'Menu' => Lavary\Menu\Facade::class,
C:\xampp82\htdocs\lva2\app\Console\Commands\AuthPermissionCommand.php
<?php
namespace App\Console\Commands;
use App\Models\Permission;
use Illuminate\Console\Command;
use Illuminate\Support\Str;
class AuthPermissionCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'auth:permission {name} {--R|remove}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Create Permissions for default mothods. The Names shoule be plural.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$permissions = $this->generatePermissions();
// check if its remove
if ($this->option('remove')) {
// remove permission
if (Permission::where('name', 'LIKE', '%' . $this->getNameArgument())->delete()) {
$this->warn('Permissions ' . implode(', ', $permissions) . ' deleted.');
} else {
$this->warn('No permissions for ' . $this->getNameArgument() . ' found!');
}
} else {
// create permissions
foreach ($permissions as $permission) {
Permission::firstOrCreate(['name' => $permission]);
}
$this->info('Permissions ' . implode(', ', $permissions) . ' created.');
}
}
private function generatePermissions()
{
$abilities = ['view', 'add', 'edit', 'delete', 'restore'];
$name = $this->getNameArgument();
return array_map(function ($val) use ($name) {
return $val . '_' . $name;
}, $abilities);
}
private function getNameArgument()
{
return strtolower(Str::plural($this->argument('name')));
}
}
C:\xampp82\htdocs\lva2\app\Events\Backend\UserCreated.php
<?php
namespace App\Events\Backend;
use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class UserCreated
{
use Dispatchable;
use InteractsWithSockets;
use SerializesModels;
public $user;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}
C:\xampp82\htdocs\lva2\app\Models\Permission.php
<?php
namespace App\Models;
class Permission extends \Spatie\Permission\Models\Permission
{
/**
* Default Permissions of the Application.
*/
public static function defaultPermissions()
{
return [
'view_users',
'add_users',
'edit_users',
'delete_users',
'restore_users',
'block_users',
'view_roles',
'add_roles',
'edit_roles',
'delete_roles',
'restore_roles',
'view_backups',
'add_backups',
'create_backups',
'download_backups',
'delete_backups',
];
}
/**
* Name should be lowercase.
*
* @param string $value Name value
*/
public function setNameAttribute($value)
{
$this->attributes['name'] = strtolower($value);
}
}
C:\xampp82\htdocs\lva2\app\Models\Role.php
<?php
namespace App\Models;
class Role extends \Spatie\Permission\Models\Role
{
/**
* Name should be lowercase.
*
* @param string $value Name value
*/
public function setNameAttribute($value)
{
$this->attributes['name'] = strtolower($value);
}
}
C:\xampp82\htdocs\lva2\app\Models\User.php
<?php
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Spatie\Permission\Traits\HasRoles;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Auth;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable, HasRoles, SoftDeletes;
protected $guarded = [
'id',
'updated_at',
'_token',
'_method',
'password_confirmation',
];
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'deleted_at' => 'datetime',
'date_of_birth' => 'datetime',
'email_verified_at' => 'datetime',
];
protected static function boot()
{
parent::boot();
// create a event to happen on creating
static::creating(function ($table) {
$table->created_by = Auth::id();
});
// create a event to happen on updating
static::updating(function ($table) {
$table->updated_by = Auth::id();
});
// create a event to happen on saving
static::saving(function ($table) {
$table->updated_by = Auth::id();
});
// create a event to happen on deleting
static::deleting(function ($table) {
$table->deleted_by = Auth::id();
$table->save();
});
}
}
C:\xampp82\htdocs\lva2\database\factories\UserFactory.php
<?php
namespace Database\Factories;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
*/
class UserFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = User::class;
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
$first_name = $this->faker->firstName;
$last_name = $this->faker->lastName;
$name = $first_name . ' ' . $last_name;
return [
'first_name' => $first_name,
'last_name' => $last_name,
'name' => $name,
'email' => $this->faker->unique()->safeEmail(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
'mobile' => $this->faker->phoneNumber,
'date_of_birth' => $this->faker->date,
'avatar' => 'img/default-avatar.jpg',
'gender' => $this->faker->randomElement(['Male', 'Female', 'Other']),
'email_verified_at' => now(),
'created_at' => now(),
'updated_at' => now(),
];
}
}
C:\xampp82\htdocs\lva2\database\migrations\2014_10_12_000000_create_users_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('first_name');
$table->string('last_name');
$table->string('username')->nullable();
$table->string('email')->unique();
$table->string('mobile')->nullable();
$table->string('gender')->nullable();
$table->date('date_of_birth')->nullable();
$table->timestamp('email_verified_at')->nullable();
$table->string('password')->nullable();
$table->string('avatar')->nullable()->default('img/default-avatar.jpg');
$table->tinyInteger('status')->default(1)->unsigned();
$table->rememberToken();
$table->integer('created_by')->unsigned()->nullable();
$table->integer('updated_by')->unsigned()->nullable();
$table->integer('deleted_by')->unsigned()->nullable();
$table->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('users');
}
};
C:\xampp82\htdocs\lva2\database\seeders\Auth\PermissionRoleTableSeeder.php
<?php
namespace Database\Seeders\Auth;
use App\Models\Permission;
use App\Models\Role;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Schema;
/**
* Class PermissionRoleTableSeeder.
*/
class PermissionRoleTableSeeder extends Seeder
{
/**
* Run the database seed.
*
* @return void
*/
public function run()
{
Schema::disableForeignKeyConstraints();
// Create Roles
$super_admin = Role::create(['name' => 'super admin']);
$admin = Role::create(['name' => 'administrator']);
$manager = Role::create(['name' => 'manager']);
$executive = Role::create(['name' => 'executive']);
$user = Role::create(['name' => 'user']);
// Create Permissions
Permission::firstOrCreate(['name' => 'view_backend']);
Permission::firstOrCreate(['name' => 'edit_settings']);
Permission::firstOrCreate(['name' => 'view_logs']);
$permissions = Permission::defaultPermissions();
foreach ($permissions as $perms) {
Permission::firstOrCreate(['name' => $perms]);
}
Artisan::call('auth:permission', [
'name' => 'posts',
]);
echo "\n _Posts_ Permissions Created.";
Artisan::call('auth:permission', [
'name' => 'categories',
]);
echo "\n _Categories_ Permissions Created.";
Artisan::call('auth:permission', [
'name' => 'tags',
]);
echo "\n _Tags_ Permissions Created.";
Artisan::call('auth:permission', [
'name' => 'comments',
]);
echo "\n _Comments_ Permissions Created.";
echo "\n\n";
// Assign Permissions to Roles
$admin->givePermissionTo(Permission::all());
$manager->givePermissionTo('view_backend');
$executive->givePermissionTo('view_backend');
Schema::enableForeignKeyConstraints();
}
}
C:\xampp82\htdocs\lva2\database\seeders\Auth\UserRoleTableSeeder.php
<?php
namespace Database\Seeders\Auth;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Schema;
/**
* Class UserRoleTableSeeder.
*/
class UserRoleTableSeeder extends Seeder
{
/**
* Run the database seed.
*
* @return void
*/
public function run()
{
Schema::disableForeignKeyConstraints();
User::findOrFail(1)->assignRole('super admin');
User::findOrFail(2)->assignRole('administrator');
User::findOrFail(3)->assignRole('manager');
User::findOrFail(4)->assignRole('executive');
User::findOrFail(5)->assignRole('user');
Schema::enableForeignKeyConstraints();
}
}
C:\xampp82\htdocs\lva2\database\seeders\Auth\UserTableSeeder.php
<?php
namespace Database\Seeders\Auth;
use App\Events\Backend\UserCreated;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Schema;
/**
* Class UserTableSeeder.
*/
class UserTableSeeder extends Seeder
{
/**
* Run the database seed.
*
* @return void
*/
public function run()
{
Schema::disableForeignKeyConstraints();
$faker = \Faker\Factory::create();
// Add the master administrator, user id of 1
$users = [
[
'first_name' => 'Super',
'last_name' => 'Admin',
'name' => 'Super Admin',
'email' => 'super@admin.com',
'password' => Hash::make('secret'),
'username' => '100001',
'mobile' => $faker->phoneNumber,
'date_of_birth' => $faker->date,
'avatar' => 'img/default-avatar.jpg',
'gender' => $faker->randomElement(['Male', 'Female', 'Other']),
'email_verified_at' => Carbon::now(),
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
],
[
'first_name' => 'Admin',
'last_name' => 'Istrator',
'name' => 'Admin Istrator',
'email' => 'admin@admin.com',
'password' => Hash::make('secret'),
'username' => '100002',
'mobile' => $faker->phoneNumber,
'date_of_birth' => $faker->date,
'avatar' => 'img/default-avatar.jpg',
'gender' => $faker->randomElement(['Male', 'Female', 'Other']),
'email_verified_at' => Carbon::now(),
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
],
[
'first_name' => 'Manager',
'last_name' => 'User User',
'name' => 'Manager',
'email' => 'manager@manager.com',
'password' => Hash::make('secret'),
'username' => '100003',
'mobile' => $faker->phoneNumber,
'date_of_birth' => $faker->date,
'avatar' => 'img/default-avatar.jpg',
'gender' => $faker->randomElement(['Male', 'Female', 'Other']),
'email_verified_at' => Carbon::now(),
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
],
[
'first_name' => 'Executive',
'last_name' => 'User',
'name' => 'Executive User',
'email' => 'executive@executive.com',
'password' => Hash::make('secret'),
'username' => '100004',
'mobile' => $faker->phoneNumber,
'date_of_birth' => $faker->date,
'avatar' => 'img/default-avatar.jpg',
'gender' => $faker->randomElement(['Male', 'Female', 'Other']),
'email_verified_at' => Carbon::now(),
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
],
[
'first_name' => 'General',
'last_name' => 'User',
'name' => 'General User',
'email' => 'user@user.com',
'password' => Hash::make('secret'),
'username' => '100005',
'mobile' => $faker->phoneNumber,
'date_of_birth' => $faker->date,
'avatar' => 'img/default-avatar.jpg',
'gender' => $faker->randomElement(['Male', 'Female', 'Other']),
'email_verified_at' => Carbon::now(),
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
],
];
foreach ($users as $user_data) {
$user = User::create($user_data);
event(new UserCreated($user));
}
Schema::enableForeignKeyConstraints();
}
}
C:\xampp82\htdocs\lva2\database\seeders\AuthTableSeeder.php
<?php
namespace Database\Seeders;
use Database\Seeders\Auth\PermissionRoleTableSeeder;
use Database\Seeders\Auth\UserRoleTableSeeder;
use Database\Seeders\Auth\UserTableSeeder;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Schema;
/**
* Class AuthTableSeeder.
*/
class AuthTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Schema::disableForeignKeyConstraints();
// Reset cached roles and permissions
app()['cache']->forget('spatie.permission.cache');
$this->call(UserTableSeeder::class);
$this->call(PermissionRoleTableSeeder::class);
$this->call(UserRoleTableSeeder::class);
Schema::enableForeignKeyConstraints();
}
}
Và kết quả thật tuyệt vời