DcatAdmin 根據選單資料自動填充許可權資訊 (Artisan命令)

Slowlyo發表於2022-05-06

寫這個的原因: 使用Dcat時配一遍選單還得再去配一遍許可權, 感覺比較麻煩主要是懶就自己寫了一個命令來生成基本的許可權資訊, 也可以用來同步不同環境的選單資訊

實現

app/Console/Commands下新建檔案DcatMenuCommand.php貼入如下內容
編寫Artisan命令 - 文件

<?php

namespace App\Console\Commands;

use Dcat\Admin\Models\Menu;
use Illuminate\Support\Str;
use Illuminate\Console\Command;
use Dcat\Admin\Models\Permission;
use Illuminate\Support\Facades\DB;

class DcatMenuCommand extends Command
{
    protected $signature = 'admin:menu';

    protected $description = 'backup or populate menu data';

    private $backupPath = '';

    public function handle()
    {
        $type = $this->ask(<<<TEXT
Please select an action type:
1: backup only
2: fill only
3: backup and fill
TEXT
        );

        $this->backupPath = storage_path('menu-backup.bak');

        switch ($type) {
            case 1: // backup only
                $this->backupMenu();
                break;
            case 2: // fill only
                $this->fillMenu();
                break;
            case 3: // backup and fill
                $this->backupAndFillMenu();
                break;
            default:
                echo 'Please enter the correct action type';
                break;
        }
    }

    /**
     * backup menu
     */
    private function backupMenu()
    {
        $res = file_put_contents($this->backupPath, serialize(optional(Menu::get())->toArray()));

        echo $res ? 'Backup succeeded' : 'Backup failed';
    }

    /**
     * fill menu
     */
    private function fillMenu()
    {
        $menu = unserialize(file_get_contents($this->backupPath));

        $permission = $this->generatePermissions($menu);

        Menu::truncate();
        Menu::insert($menu);

        Permission::truncate();
        Permission::insert($permission);

        DB::table('admin_permission_menu')->truncate();
        foreach ($permission as $item) {
            $query = DB::table('admin_permission_menu');
            $query->insert([
                'permission_id' => $item['id'],
                'menu_id'       => $item['id'],
            ]);
            if ($item['parent_id'] != 0) {
                $query->insert([
                    'permission_id' => $item['id'],
                    'menu_id'       => $item['parent_id'],
                ]);
            }
        }

        echo 'Filled successfully';
    }

    /**
     * Back up and populate the menu
     */
    private function backupAndFillMenu()
    {
        $this->backupMenu();
        $this->fillMenu();
    }

    /**
     * Generate permission data
     *
     * @param $menu
     *
     * @return array
     */
    private function generatePermissions($menu)
    {
        $permissions = [];
        foreach ($menu as $item) {
            $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'] = $item['created_at'];
            $temp['updated_at'] = $item['updated_at'];

            $permissions[] = $temp;
            unset($temp);
        }

        return $permissions;
    }

    /**
     * Get http path according to menu uri
     *
     * @param $uri
     *
     * @return string
     */
    private function getHttpPath($uri)
    {
        if ($uri == '/') {
            return '';
        }

        if ($uri == '') {
            return '';
        }

        if (strpos($uri, '/') !== 0) {
            $uri = '/' . $uri;
        }

        return $uri . '*';
    }
}

使用方式

在專案根目錄執行命令php artisan admin:menu會得到如下提示 (然後輸入1/2/3執行對應操作)

Please select an action type:
1: backup only
2: fill only
3: backup and fill:
 >

1: 備份選單-查詢出所有選單資料序列化後寫入storage/menu-backup.bak檔案中
2: 填充選單-讀出storage/menu-backup.bak中的內容並寫入資料庫
3: 備份並填充-依次執行1~2的操作

!! 填充操作會 清空 truncate 原有的選單表 admin_menu、許可權表 admin_permissions、許可權選單關聯表 admin_permission_menu 然後再寫入資料

! 該命令只是把選單一一對應的搬到許可權表中, 更細緻的許可權控制還是得自己動手新增

本作品採用《CC 協議》,轉載必須註明作者和本文連結
海到無涯天作案,山登絕頂我為峰

相關文章