Laravel11 從0開(kāi)發(fā) Swoole-Reverb 擴(kuò)展包(一) - 擴(kuò)展包開(kāi)發(fā)
前言
大家好呀,我是yangyang。好久沒(méi)更新了,最近新項(xiàng)目在使用laravel11(截止目前發(fā)文,laravel12也發(fā)布了)做開(kāi)發(fā),自己也是利用有些空閑時(shí)間做些除開(kāi)業(yè)務(wù)以外的深入學(xué)習(xí),因此也就萌生了做一個(gè)系列隨筆文章的想法。
laravel11
Laravel 11 繼續(xù)改進(jìn) Laravel 10.x,通過(guò)引入簡(jiǎn)化的應(yīng)用程序結(jié)構(gòu)、每秒速率限制、健康路由、優(yōu)雅的加密密鑰輪換、隊(duì)列測(cè)試改進(jìn)、Resend 郵件傳輸、Prompt 驗(yàn)證器集成、新的 Artisan 命令等。此外,Laravel Reverb,一個(gè)官方的可擴(kuò)展 WebSocket 服務(wù)器也被引入,為您的應(yīng)用程序提供強(qiáng)大的實(shí)時(shí)功能。
————————————————
開(kāi)篇
laravel Reverb
Laravel Reverb 由 Joe Dixon 開(kāi)發(fā)。Laravel Reverb 為 Laravel 應(yīng)用程序帶來(lái)了極速且可擴(kuò)展的實(shí)時(shí) WebSocket 通信,并與 Laravel 現(xiàn)有的事件廣播工具(如 Laravel Echo)無(wú)縫集成。此外,Reverb 支持通過(guò) Redis 的發(fā)布 / 訂閱功能進(jìn)行水平擴(kuò)展,使您能夠?qū)?WebSocket 流量分布在多個(gè)后端 Reverb 服務(wù)器上,從而支持單個(gè)高需求應(yīng)用程序。
有關(guān) Laravel Reverb 的更多信息,請(qǐng)查閱完整的 Reverb 文檔。
開(kāi)發(fā)原由
24年出了一些關(guān)于Reverb混響的一些隨筆,最近也簡(jiǎn)單跟蹤了下它的源碼,laravel無(wú)愧于設(shè)計(jì)大神,Joe Dixon 大佬的封裝設(shè)計(jì)實(shí)現(xiàn)非常到位,以至于云里霧里的。Reverb在ws+http混合服務(wù)使用的react-php實(shí)現(xiàn),想著國(guó)內(nèi)(個(gè)人認(rèn)知,不代表所有)用它不多,多是swoole、workerman。于是就想到了用swoole來(lái)復(fù)刻一個(gè)版本,一開(kāi)始,準(zhǔn)備基于Reverb來(lái)擴(kuò)展swoole并支持替換react-php。發(fā)現(xiàn)代碼設(shè)計(jì)關(guān)聯(lián)很多,我個(gè)人難以撼動(dòng),于是另辟蹊徑,做一個(gè)新的擴(kuò)展包。
因此,在本系列文章中,我將分享如何從零開(kāi)始為 Laravel11 開(kāi)發(fā)一個(gè)自定義擴(kuò)展包——Swoole-Reverb,目前這個(gè)擴(kuò)展包我也抽空開(kāi)發(fā),在開(kāi)發(fā)過(guò)程中,我遇到了一些問(wèn)題,如果我覺(jué)得有用,我會(huì)第一時(shí)間總結(jié)一些方案,希望能為大家提供一些參考和幫助。最后,也希望能夠像到Joe Dixon大神的水準(zhǔn)看齊。
一、項(xiàng)目結(jié)構(gòu)和初始設(shè)置
首先,我們?cè)?Laravel 應(yīng)用的同級(jí)目錄下創(chuàng)建了一個(gè) core 目錄,并在其中放置 Swoole-Reverb 擴(kuò)展包的代碼。基本的目錄結(jié)構(gòu)如下:
project-root/
├── app/
├── core/
│ └── SwooleReverb/
│ └── src/
│ ├── Providers/
│ │ ├── BroadcastServiceProvider.php
│ │ └── SwooleReverbServiceProvider.php
│ └── Broadcasting/
│ └── SwooleBroadcaster.php
└── composer.json
在主項(xiàng)目的 composer.json 文件中,我們通過(guò) autoload 配置引入了 Swoole-Reverb 的命名空間:
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/",
"SwooleReverb\\": "core/SwooleReverb/src/"
}
}
同時(shí),在 extra 部分配置了 Laravel 的自動(dòng)發(fā)現(xiàn)信息:
"extra": {
"laravel": {
"providers": [
"SwooleReverb\\Providers\\BroadcastServiceProvider",
"SwooleReverb\\Providers\\SwooleReverbServiceProvider"
]
}
}
目前考慮到開(kāi)發(fā)方便,一開(kāi)始的操作是這樣的,后期在做獨(dú)立包。
注意:自動(dòng)發(fā)現(xiàn)機(jī)制只針對(duì)通過(guò) Composer 安裝到 vendor 目錄中的包生效。如果你把包直接放在項(xiàng)目根目錄外(比如
core目錄下),Laravel 不會(huì)自動(dòng)發(fā)現(xiàn)這些包。解決辦法可以是通過(guò) 本地路徑倉(cāng)庫(kù) 將包安裝進(jìn) vendor 中,或者直接手動(dòng)注冊(cè)服務(wù)提供者。
二、自動(dòng)發(fā)現(xiàn)問(wèn)題和手動(dòng)注冊(cè)
但是按照我上面的方式,在開(kāi)發(fā)過(guò)程中,我發(fā)現(xiàn)執(zhí)行 php artisan vendor:publish 無(wú)法找到 Swoole-Reverb 的服務(wù)提供者。經(jīng)過(guò)排查,主要原因是 Laravel 自動(dòng)發(fā)現(xiàn)機(jī)制不支持直接放在項(xiàng)目根目錄的擴(kuò)展包。
解決方案
- 本地路徑倉(cāng)庫(kù)方式
在主項(xiàng)目的composer.json中添加如下配置,將 repositories 改為數(shù)組形式并追加本地路徑倉(cāng)庫(kù):
然后在"repositories": [ { "type": "composer", "url": "https://packagist.org" }, { "type": "path", "url": "core/SwooleReverb" } ]core/SwooleReverb下的composer.json中配置包的基本信息以及自動(dòng)發(fā)現(xiàn)信息,示例如下:
然后執(zhí)行:{ "name": "wanzij/swoole-reverb", "autoload": { "psr-4": { "SwooleReverb\\": "src/" } }, "extra": { "laravel": { "providers": [ "SwooleReverb\\Providers\\BroadcastServiceProvider", "SwooleReverb\\Providers\\SwooleReverbServiceProvider" ] } } }composer require wanzij/swoole-reverb:"dev-main"提示:最初使用
dev-master可能會(huì)報(bào)錯(cuò),因?yàn)榘种Q(chēng)可能已經(jīng)從 master 改為了 main。
這個(gè)流程就是正確完整的擴(kuò)展包開(kāi)發(fā)流程。
- 手動(dòng)注冊(cè)服務(wù)提供者
當(dāng)然在前期的開(kāi)發(fā)中,我們?yōu)榱朔奖?,上面的方式更可取,因?yàn)椴挥妹看胃麓a后,執(zhí)行composer update更新,所以如果不想采用本地路徑倉(cāng)庫(kù)的方式,也可以直接在config/app.php中手動(dòng)注冊(cè)服務(wù)提供者:
這樣可以確保服務(wù)提供者被加載。'providers' => [ // 其他服務(wù)提供者... SwooleReverb\Providers\BroadcastServiceProvider::class, SwooleReverb\Providers\SwooleReverbServiceProvider::class, ],
三、開(kāi)發(fā)中的常見(jiàn)問(wèn)題及解決方案
1. 類(lèi)找不到或命名空間錯(cuò)誤
- 問(wèn)題:在執(zhí)行
php artisan vendor:publish時(shí)找不到服務(wù)提供者。 - 解決:確認(rèn)
composer dump-autoload已執(zhí)行,檢查目錄結(jié)構(gòu)和文件頂部的命名空間是否正確。
2. 依賴(lài)容器綁定錯(cuò)誤
- 問(wèn)題:使用
$this->app->make('broadcast')報(bào)Target class [broadcast] does not exist.錯(cuò)誤。 - 解決:可以直接使用完整類(lèi)名
\Illuminate\Broadcasting\BroadcastManager::class來(lái)獲取實(shí)例,例如:$this->app->make(\Illuminate\Broadcasting\BroadcastManager::class)->extend('swoole', function ($app, $config) { return new SwooleBroadcaster( $config['host'] ?? 'localhost', $config['port'] ?? 8084, $config['options'] ?? [] ); });
3. Composer 版本穩(wěn)定性問(wèn)題
- 問(wèn)題:安裝包時(shí)提示最低穩(wěn)定性問(wèn)題,例如:
Could not find a version of package wanzij/swoole-reverb matching your minimum-stability (stable). - 解決:
- 顯式指定使用開(kāi)發(fā)版:
composer require wanzij/swoole-reverb:"dev-main" - 或者在主項(xiàng)目
composer.json中調(diào)整最低穩(wěn)定性:"minimum-stability": "dev", "prefer-stable": true
- 顯式指定使用開(kāi)發(fā)版:
四、總結(jié)
看完后,我們關(guān)心的點(diǎn)又: Laravel 的自動(dòng)發(fā)現(xiàn)機(jī)制、 Composer 的本地路徑倉(cāng)庫(kù)配置以及容器綁定的相關(guān)問(wèn)題。
后續(xù)我會(huì)繼續(xù)分享更多關(guān)于擴(kuò)展包開(kāi)發(fā)的細(xì)節(jié)和實(shí)踐經(jīng)驗(yàn),敬請(qǐng)關(guān)注!
如果有任何問(wèn)題或建議,歡迎在評(píng)論區(qū)留言討論。
更多文檔參考:

浙公網(wǎng)安備 33010602011771號(hào)