禁用admin.php中
'menu' => [
#角色繫結選單
"role_bind_menu" => false
]
<?php
namespace App\Console\Commands;
use Illuminate\Support\Str;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
class GeneratePermission extends Command
{
#命令
protected $signature = 'admin:menu-permission';
#描述
protected $description = '備份選單,填充選單資料,填充許可權';
#磁碟地址
protected $disk;
#備份檔案路徑
protected $backup_path = 'backup/menu.bak';
#選單模型
protected $menu_model;
#許可權模型
protected $permission_model;
#選單,許可權中間表名
protected $permission_menu_table;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
$this->menu_model = config('admin.database.menu_model');
$this->permission_model = config('admin.database.permissions_model');
$this->permission_menu_table = config('admin.database.permission_menu_table');
$this->disk = Storage::disk(config('admin.upload.disk'));
}
/**
* @description:
* @Author:AKE
* @Date:2022/5/7 10:40
*/
public function handle()
{
$type = $this->choice('請選擇要執行的步驟', [
'備份選單', '填充許可權', '填充選單'
],0);
switch ($type){
case '備份選單':
$this->generateBackup();
break;
case '填充許可權':
$this->fillpermission();
break;
case '填充選單':
$this->fillMenu();
break;
default:
$this->error('請選擇要執行的步驟');
break;
}
}
/**
* @description:生成備份檔案
* @Author:AKE
* @Date:2022/5/7 9:46
*/
private function generateBackup()
{
#獲取選單資料
$arr = optional((new $this->menu_model())->get())->toArray();
#寫入檔案
$res = $this->disk->put($this->backup_path, serialize($arr));
$res ? $this->info('備份成功') : $this->error('備份失敗');
}
/**
* @description:填充許可權
* @Author:AKE
* @Date:2022/5/7 10:54
*/
private function fillPermission()
{
$disk = $this->disk;
#判斷備份檔案是否存在
$exist = $disk->exists($this->backup_path);
if (!$exist) {
$this->error('請先進行選單備份');
return;
}
#獲取資料並反序列化
$menu = unserialize($disk->get($this->backup_path));
#資料組裝
$permission = $this->generatePermissions($menu);
DB::beginTransaction();
try {
$this->info('清除許可權表...');
#清空許可權表
(new $this->permission_model())->truncate();
$this->info('清除完成');
$this->info('填充許可權...');
$this->withProgressBar($permission, function ($permission){
#填充許可權表
(new $this->permission_model())->insert($permission);
});
$this->newLine();
$this->info('許可權填充完成');
$this->info('清除許可權選單中間表...');
#清空許可權,選單中間表
DB::table($this->permission_menu_table)->truncate();
$this->info('清除完成');
$this->info('填充許可權選單中間表...');
$bar = $this->output->createProgressBar(count($permission));
$bar->start();
#迴圈插入許可權選單中間表
foreach ($permission as $item) {
$query = DB::table($this->permission_menu_table);
#選單id和許可權id
$query->insert([
'permission_id' => $item['id'],
'menu_id' => $item['id'],
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
#如果不是頂級,則另外繫結父級選單
if ($item['parent_id'] != 0) {
$this->recursive($item['id'], $item['parent_id']);
}
$bar->advance();
}
$bar->finish();
$this->newLine();
$this->info('許可權選單中間表填充完成');
DB::commit();
$this->info('許可權填充完成');
}catch (\Exception $exception){
DB::rollBack();
$this->error($exception->getMessage());
$this->newLine();
$this->error('許可權填充失敗');
}
}
/**
* @description:遞迴,新增許可權(為了有三級或者四級的選單的情況)
* @param $id
* @param $parent_id
* @Author:AKE
* @Date:2022/5/16 16:47
*/
private function recursive($id, $parent_id)
{
if ($parent_id != 0){
$query = DB::table($this->permission_menu_table);
$query->insert([
'permission_id' => $id,
'menu_id' => $parent_id,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
$parent_id = (new $this->permission_model())->where('id', $parent_id)->value('parent_id');
if ($parent_id != 0){
$this->recursive($id, $parent_id);
}
}
}
/**
* @description:填充選單
* @Author:AKE
* @Date:2022/5/7 13:20
*/
private function fillMenu()
{
$disk = $this->disk;
#判斷備份檔案是否存在
$exist = $disk->exists($this->backup_path);
if (!$exist) {
$this->error('請先進行選單備份');
return;
}
#獲取資料並反序列化
$menu = unserialize($disk->get($this->backup_path));
DB::beginTransaction();
try {
$this->info('清除選單表...');
#清空選單表
(new $this->menu_model())->truncate();
$this->info('清除完成');
$this->info('填充選單...');
$this->withProgressBar($menu, function ($menu){
#選單表資料填充
(new $this->menu_model())->insert($menu);
});
$this->newLine();
$this->info('選單填充完成');
DB::commit();
}catch (\Exception $exception){
DB::rollBack();
$this->error($exception->getMessage());
$this->newLine();
$this->error('填充失敗');
}
}
/**
* @description:生成許可權
* @param $menu
* @return array
* @Author:AKE
* @Date:2022/5/7 10:47
*/
private function generatePermissions($menu)
{
$permissions = [];
#迴圈整合資料
foreach ($menu as $item) {
#第一條不加入許可權(第一條為主頁,預設所有管理員都可以看到)
if ($item['id'] == 1) continue;
$temp = [];
$temp['id'] = $item['id'];
$temp['name'] = $item['title'];
$temp['slug'] = (string)Str::uuid();
$temp['http_path'] = $this->getHttpPath($item['uri']);
$temp['order'] = $item['order'];
$temp['parent_id'] = $item['parent_id'];
$temp['created_at'] = date('Y-m-d H:i:s');
$temp['updated_at'] = date('Y-m-d H:i:s');
$permissions[] = $temp;
unset($temp);
}
return $permissions;
}
/**
* @description:生成許可權連結
* @param $uri
* @return string
* @Author:AKE
* @Date:2022/5/7 10:47
*/
private function getHttpPath($uri)
{
if ($uri == '/' || $uri == '') return '';
if (strpos($uri, '/') !== 0) $uri = '/' . $uri;
#為了防止有兩個一樣的路由故這樣寫,例如 /index 和 /index-a 等
#如果沒有可以直接寫成 $uri . '*'
return $uri . ',' . $uri . '/*';
}
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結