Laravel通用外掛

Wangds發表於2020-11-13

開發中,未上線

一個使您的 Laravel 專案獲得即插即用外掛功能的擴充套件。

專案概述

啟發於 WordPress,安裝 GalleryPlugin (以下簡稱 GP )後,您的 Laravel 專案即可擁有即插即用的外掛擴充套件能力。

外掛需要基於 GP 並配合相應的 鉤子放置策略 專門開發。

外掛可釋出到 Composer 並通過其安裝。

使用場景

假設您在用 Laravel 開發一套 CMS 系統,
當您想要對它增加外掛能力,以便為您的使用者提供熱插拔外掛的功能時,
您可以選擇 GP

專案安裝 GP 後,按需放置鉤子,然後按照 鉤子放置策略 開發相應的外掛。

外掛釋出後,使用此 CMS 系統的使用者即可安裝此外掛以擴充套件其網站的功能。

功能

  • 安裝外掛 —— 從 Composer 下載外掛並安裝
  • 啟用外掛 —— 修改外掛狀態以啟用
  • 禁用外掛 —— 修改外掛狀態以禁用
  • 解除安裝外掛 —— 刪除外掛,可選擇是否保留資料
  • 外掛列表 —— 獲取外掛列表
  • 掛載鉤子 —— 向鉤子掛載函式或方法
  • 執行鉤子 —— 執行鉤子上掛載的函式或方法
  • 禁用鉤子 —— 禁止執行鉤子
  • 解除安裝鉤子 —— 解除安裝鉤子上掛載的函式或方法
  • 鉤子列表 —— 獲取鉤子列表

環境要求

  • PHP 7.0+
  • Mysql 5.7+
  • Laravel 5.8+

安裝

composer require xxx/plugin
php artisan vendor:publish --provider=Gallery\Plugin\PluginServiceProvider
php artisan migrate
  • 通過原始碼安裝

首先下載 原始碼包,解壓後放在你希望放在的位置。

在 Composer 配置中新增 classmap 引數,如:

{
    "autolaod": {
        "classmap": [
            "專案中 GP 資料夾的路徑"
        ]
    }
}

執行 composer dump-autoload

最後把 \Gallery\Plugin\PluginServiceProvider::class
放到 config/app.phpproviders 中。

核心概念

鉤子原理

鉤子是程式執行過程中特定的點或事件,把外掛的一個或多個函式或方法掛載到鉤子上,就可以在指定的時機呼叫他們。

鉤子型別

  • 動作鉤子

    激發鉤子時,鉤子按優先順序 priority 從小到大的順序呼叫掛載其上的所有函式或方法;
    同優先順序下按先後掛載的次序先後呼叫;
    呼叫是相互獨立的,可傳遞多個引數,每個函式或方法接收的引數都是相同的。

  • 過濾器鉤子

    激發鉤子時,鉤子按優先順序 priority 從小到大的順序呼叫掛載其上的所有函式或方法;
    同優先順序下按先後掛載的次序先後呼叫;
    呼叫是串聯接力的,只傳遞單一引數,函式或方法的返回值是其後函式或方法的引數。

  • 一次性鉤子

    激發鉤子時,只呼叫一個函式或方法,且呼叫的是按照上面?描述的執行次序的第一個函式或方法。

放置策略

事實上每一個專案都有不同的需求和不同的結構。
在哪裡放置鉤子,鉤子是什麼型別,放置多少鉤子,每個專案都是不同的,或者說很難做到一致。
因此,不同的專案有不同的放置策略,基於某一策略開發的外掛難以在另一個專案中使用。一個專案只能安裝符合它的放置策略的外掛。

當專案升級時,放置策略可能會發生變化,專案開發者要考慮長遠,儘量滿足較小差異下的相容性。
當然如果難以相容或差異較大,專案開發者就要有放棄所有舊版本外掛的準備,或者自己升級外掛,或者鼓勵外掛開發者社群更新他們的外掛。

策略標籤

對於不同的 鉤子放置策略,我們用 策略標籤 加以區分。

例如,有A專案整合了 GP,在概念上誕生了A專案的策略標籤,不妨叫 a-strategy-v1.0
只要是滿足 a-strategy-v1.0 策略的外掛,就可以安裝在A專案上。

同時,同一個策略標籤還可能有不同的版本,小版本之間需滿足相容性,大版本之間不能混用。

如果某外掛同時支援多種不同的策略,那麼它可以應用在不同的專案中。建議多做測試。

使用

安裝外掛

composer require foo/bar
php artisan gallery:add foo_bar
  • 通過原始碼安裝

首先下載 原始碼包,解壓後放在專案的外掛資料夾中 /plugins(憑你喜好)。

在 Composer 中新增 classmap 引數,如:

{
    "autolaod": {
        "classmap": [
            "plugins/"
        ]
    }
}

執行 composer dump-autoload

\Foo\Bar\BarServiceProvider::class 放到 config/app.phpproviders 中。

最後執行:

  • 命令列方式:

    php artisan gallery:add foo_bar
  • 程式碼方式:

    $res = \Gallery\Plugin\Plugin::addPlugin('foo_bar');

啟用外掛

  • 命令列方式:

    php artisan gallery:enable foo_bar
  • 程式碼方式:

    $res = \Gallery\Plugin\Plugin::enablePlugin('foo_bar');

禁用外掛

  • 命令列方式:

    php artisan gallery:disable foo_bar
  • 程式碼方式:

    $res = \Gallery\Plugin\Plugin::disablePlugin('foo_bar');

解除安裝外掛

  • 命令列方式:

    php artisan gallery:remove foo_bar
  • 程式碼方式:

    $res = \Gallery\Plugin\Plugin::removePlugin('foo_bar');

外掛列表

  • 命令列方式:

    php artisan gallery:plugin-list
  • 程式碼方式:

    $plugins = \Gallery\Plugin\Plugin::getPlugins();

掛載鉤子

// 在外掛中註冊鉤子
add('init', function(){
    echo '本段文字將在系統初始化時輸出';
});

執行鉤子

// 在業務流程或檢視中執行鉤子
play('init');

禁用鉤子

把外掛的 status 欄位改成 0

return [
    'hooks' => [
        'init' => [
            'name' => 'init',
            'type' => 1,
            'desc' => 'PluginServiceProvider::boot()執行時',
            'status' => 0
        ]
    ]
];

鉤子列表

\Gallery\Plugin\Plugin::getHooks();
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章