- 后端
- 微服务
【免费下载链接】hyperf
🚀 A coroutine framework that focuses on hyperspeed and flexibility. Building microservice or middleware with ease.
Hyperf 是一個基於 Swoole/Swow 的高效能協程框架,其生態的核心在於「元件化」設計——幾乎所有能力都以獨立元件的形式提供,開發者也可以開發自己的元件來擴充套件框架、共建生態。本文聚焦元件開發的第一步:如何使用官方提供的hyperf/component-creator工具快速搭建元件包骨架,以及如何在專案中透過 Composer 的path倉庫來源引入尚未釋出到 Packagist 的元件,並結合當前倉庫的原始碼講解元件被框架識別與載入的底層機制。讀完本文,你將掌握「從零建立元件包 → 本地開發調試 → 配置釋出」的完整閉環。
元件開發的前置認知
在動手建立元件之前,有必要先理解 Hyperf 元件化開發的定位。與傳統 PHP-FPM 架構下「透過 Composer 直接引入一個庫(Library)」的模式不同,Hyperf 具備持久化應用與協程兩個特性,導致應用生命週期與執行模式存在較大差異,因此並非所有第三方庫都能在 Hyperf 中直接使用。元件開發指南的前言明確指出:在閱讀本指南前,建議先全面閱讀 協程 與 依賴注入 章節,對 Hyperf 的基礎元件有充分理解後再開始元件開發。
元件開發的核心思想是:元件自身保持「低耦合、高獨立、可重用」,元件之間的解耦依賴於ConfigProvider機制——每個元件提供一個ConfigProvider類,在框架啟動時被載入並合併到全域配置中,完成元件的配置初始化。關於該機制的完整說明,可參閱 ConfigProvider 機制,下文也會結合原始碼展開。
使用官方工具建立新的元件包
Hyperf官方提供了hyperf/component-creator工具來快速建立元件包,這是元件開發的最簡潔起點。透過composer create-project即可生成一個適配目標版本、結構完整的元件骨架:
# 建立適配 Hyperf 最新版本的元件包 composer create-project hyperf/component-creator your_component dev-master # 建立適配 Hyperf 2.0 版本的元件包 composer create-project hyperf/component-creator your_component "2.0.*"其中your_component是元件包的目錄名(同時也應作為包名的一部分),dev-master或"2.0.*"用於指定建立工具自身對應的版本分支,從而生成與目標 Hyperf 主版本匹配的元件骨架。
從當前倉庫的實際結構看,一個標準元件包通常具備以下形態(以hyperf/amqp為例):
src/:PSR-4 自動載入的原始碼目錄,包含元件核心類;publish/:元件預設配置檔案目錄(如 publish 配置),用於後續vendor:publish釋出;tests/:單元測試目錄;composer.json:元件描述檔案,其中extra.hyperf.config指向元件根目錄下的ConfigProvider類;ConfigProvider.php:元件配置提供者,位於元件根目錄。
在專案中使用未釋出的元件包
元件建立完成後、正式釋出到 Packagist 之前,你可能需要在實際專案中先行使用、調試。Composer 原生支援path型別的倉庫來源,可以將本地目錄作為依賴來源引入,這正是 Hyperf 官方文件推薦的本地開發方案。
假設專案目錄結構如下:
/opt/project // 專案目錄 /opt/your_component // 元件包目錄假設元件名為your_component/your_component,則需修改/opt/project/composer.json(以下省略其他不相干的配置):
{ "require": { "your_component/your_component": "dev-master" }, "repositories": { "your_component": { "type": "path", "url": "/opt/your_component" } } }最後在目錄/opt/project中執行composer update -o即可完成依賴更新。-o(即--optimize-autoloader)會在更新依賴的同時優化自動載入器,將 PSR-4 等規則轉換為更高效的 classmap,在 path 倉庫場景下能保證本地元件的類被準確、快速地載入。
這種path來源的寫法同樣適用於開發 Hyperf 自身元件:在指南前言中,官方建議在同一目錄下分別安裝hyperf/hyperf-skeleton骨架專案與hyperf/hyperf元件庫,並在骨架專案的composer.json中將repositories指向../hyperf/src/*,這樣vendor/hyperf下的元件目錄全部以軟連結(softlink)方式指向原始碼目錄,開發者可以在 IDE 中直接修改vendor/hyperf內的檔案(實際修改的是原始碼),最終提交 PR 到主幹,實現「邊開發邊驗證」的工作流。
元件被框架識別的關鍵:ConfigProvider 與 composer.json 的 extra 配置
建立一個類並不會被 Hyperf 自動載入。元件要想在 Hyperf 框架啟動時被掃描、初始化,必須在元件的composer.json中宣告extra.hyperf.config,指定元件根目錄下ConfigProvider類的名稱空間:
{ "name": "hyperf/foo", "require": { "php": ">=7.3" }, "autoload": { "psr-4": { "Hyperf\\Foo\\": "src/" } }, "extra": { "hyperf": { "config": "Hyperf\\Foo\\ConfigProvider" } } }定義之後需執行composer install或composer update或composer dump-autoload等會讓 Composer 重新生成composer.lock檔案的命令,才能被正常讀取。
為什麼必須重新生成composer.lock?從原始碼可以看出端倪:Composer 工具類中的getMergedExtra()方法會先透過getLockContent()讀取專案根目錄下的composer.lock,解析出所有已安裝包的extra欄位(src/support/src/Composer.php):
public static function getMergedExtra(?string $key = null): array { if (! self::$extra) { self::getLockContent(); } // 將所有包 extra 中指定 key 的配置按規則合併 // 陣列值使用 array_merge 合併,非陣列值以追加方式收集 ... }也就是說,框架是從composer.lock的packages/packages-dev中提取每個包的extra資訊(src/support/src/Composer.php),因此只有執行上述任一命令讓composer.lock包含新元件的extra欄位後,元件才能被框架感知。
以倉庫內真實元件hyperf/amqp為例,其 composer.json 中宣告:
"extra": { "branch-alias": { "dev-master": "3.2-dev" }, "hyperf": { "config": "Hyperf\\Amqp\\ConfigProvider" } }而 Hyperf\Amqp\ConfigProvider 則返回了該元件的依賴綁定、事件監聽器與待釋出配置等完整資訊:
class ConfigProvider { public function __invoke(): array { return [ 'dependencies' => [ Producer::class => Producer::class, Packer::class => JsonPacker::class, Consumer::class => ConsumerFactory::class, ], 'listeners' => [ BeforeMainServerStartListener::class => 99, MainWorkerStartListener::class, ], 'publish' => [ [ 'id' => 'config', 'description' => 'The config for amqp.', 'source' => __DIR__ . '/../publish/amqp.php', 'destination' => BASE_PATH . '/config/autoload/amqp.php', ], ], ]; } }由此可見,元件與框架的耦合被收斂到一個ConfigProvider類中,這正是「元件間解耦、元件獨立、元件可重用」的實現基礎。
ConfigProvider 的標準返回結構
ConfigProvider本身不具備任何依賴:不繼承抽象類、不要求實現介面,只需提供一個__invoke方法並返回一個配置結構陣列即可。其返回結構約定如下(完整範例見 ConfigProvider 機制):
<?php namespace Hyperf\Foo; class ConfigProvider { public function __invoke(): array { return [ // 合併到 config/autoload/dependencies.php 檔案 'dependencies' => [], // 合併到 config/autoload/annotations.php 檔案 'annotations' => [ 'scan' => [ 'paths' => [ __DIR__, ], ], ], // 預設 Command 的定義,合併到 Hyperf\Contract\ConfigInterface 內,與 config/autoload/commands.php 對應 'commands' => [], // 事件監聽器,與 commands 類似 'listeners' => [], // 元件預設配置檔案,執行 vendor:publish 命令後會把 source 對應的檔案複製為 destination 對應的檔案 'publish' => [ [ 'id' => 'config', 'description' => 'description of this config file.', // 描述 // 建議預設配置放在 publish 資料夾中,檔案命名和元件名稱相同 'source' => __DIR__ . '/../publish/file.php', // 對應的配置檔案路徑 'destination' => BASE_PATH . '/config/autoload/file.php', // 複製為這個路徑下的該檔案 ], ], // 亦可繼續定義其它配置,最終都會合併到與 ConfigInterface 對應的配置儲存器中 ]; } }需要注意的是,ConfigProvider的配置並非一定就是這樣劃分,這些只是約定俗成的格式,實際上最終如何解析這些配置的決定權在於使用者——可透過修改 Skeleton 專案的config/container.php檔案內的程式碼來調整相關載入,也就是說config/container.php決定了ConfigProvider的掃描與載入方式。
透過 vendor:publish 釋出元件預設配置
在ConfigProvider中定義好publish後,可以使用如下命令快速生成配置檔案:
php bin/hyperf.php vendor:publish 包名稱例如包名稱為hyperf/amqp,可執行命令生成amqp預設的配置檔案:
php bin/hyperf.php vendor:publish hyperf/amqp該命令的底層實現位於 VendorPublishCommand。從原始碼可以看出其完整行為(src/devtool/src/VendorPublishCommand.php):
package(必填參數):要釋出配置的包名稱;-i, --id(可選):指定要釋出的配置項id,僅釋出該項;-s, --show(可選):列出該包所有可釋出的配置項,不實際複製;-f, --force(可選):覆蓋已存在的目標檔案(預設若目標檔案已存在會跳過並提示[destination] already exists.)。
命令執行時,會透過Composer::getMergedExtra()從composer.lock中讀取該包的extra.hyperf.config,實例化對應的ConfigProvider並呼叫__invoke()取得配置陣列,再取出publish項逐個複製(src/devtool/src/VendorPublishCommand.php)。複製過程中,若目標目錄不存在會自動建立(權限 0755),若source是目錄則執行目錄複製,否則執行單檔案複製——這意味著publish不僅可以釋出單個配置檔案,也可以釋出整個目錄(例如模板、遷移檔案等)。
publish 項的欄位說明
| 欄位 | 說明 |
|---|---|
id | 配置項的唯一識別符,供vendor:publish -i精確指定使用 |
description | 該配置項的描述文字 |
source | 元件內預設配置檔案的路徑,建議放在publish/資料夾,檔案命名與元件名稱相同 |
destination | 複製到專案中的目標路徑,通常為BASE_PATH . '/config/autoload/xxx.php' |
元件設計規範
由於composer.json內的extra屬性在資料不被利用時沒有其它作用和影響,因此元件內的這些定義在其它框架使用時不會造成任何干擾,ConfigProvider是一種僅作用於 Hyperf 框架的機制,這為元件的複用打下了基礎。但這也要求在進行元件設計時,必須遵循以下規範(詳見 ConfigProvider 機制):
- 所有類的設計都必須允許透過標準
OOP方式使用,所有 Hyperf 專有功能必須作為增強功能並以單獨的類提供,也就是說在非 Hyperf 框架下仍能透過標準手段使用元件; - 元件的依賴設計優先滿足 PSR 標準);
- 對於實現 Hyperf 專有功能所增加的增強功能類,通常會依賴 Hyperf 的一些元件,這些依賴不應寫在
composer.json的require項,而應寫在suggest項作為建議項(如 amqp 的 composer.json 中將hyperf/di、hyperf/event列為suggest); - 元件設計時不應該透過註解進行任何依賴注入,注入方式應只使用建構函式注入,這樣同時也能滿足在 OOP 下的使用;
- 元件設計時不應該透過註解進行任何功能定義,功能定義應只透過
ConfigProvider來定義; - 類的設計時應盡可能不儲存狀態資料,因為這會導致類不能作為長生命週期物件提供,也無法方便地使用依賴注入,會在一定程度下降低效能;狀態資料應透過
Hyperf\Context\Context協程上下文來儲存。
結語
至此,你已經掌握了元件開發的完整起步路徑:用hyperf/component-creator建立元件骨架 → 透過 Composerpath倉庫在本地專案中引入未釋出元件進行聯調 → 用ConfigProvider定義元件配置與釋出項 → 透過vendor:publish向使用者專案釋出預設配置。在此基礎上,進一步閱讀 ConfigProvider 機制 與 指南前言(包含透過軟連結直接開發 Hyperf 自身元件的進階工作流),即可完整掌握 Hyperf 元件開發的規範與生態共建方式。
- 后端
- 微服务
【免费下载链接】hyperf
🚀 A coroutine framework that focuses on hyperspeed and flexibility. Building microservice or middleware with ease.
相关推荐
Hyperf 開發者工具(hyperf/devtool)實戰指南:代碼生成、配置發佈與 IDE 快速打開
Hyperf 開發者工具(hyperf/devtool)實戰指南:代碼生成、配置發佈與 IDE 快速打開 本指南圍繞 Hyperf 框架的開發者工具組件 hyp
后端微服务Kimi K2 驅動 Claude Code:AI 文件閱讀助手專案從使用到開發的完整實戰
Kimi K2 驅動 Claude Code:AI 文件閱讀助手專案從使用到開發的完整實戰 本文以「Kimi K2 AI 文件閱讀助手專案」為核心,完整還原一個
文档教程知识库人工智能使用 Hyperf 官方工具快速创建可复用的组件包
使用 Hyperf 官方工具快速创建可复用的组件包 导读 本文面向 Hyperf 开发者,系统讲解如何利用官方脚手架 hyperf/component crea
后端微服务
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考