有些時(shí)候在某一個(gè)項(xiàng)目中, 使用了一個(gè)第三方包, 但是會(huì)發(fā)現(xiàn)某一些地方不符合項(xiàng)目需求. 或者需要在包代碼里注入一段自己的邏輯. 我們可以選擇自己維護(hù)一個(gè)分支, 或者干脆改vendor文件夾, 并它他加入代碼管理. 但對(duì)于要修改少量代碼時(shí), 這樣做貌似不太'優(yōu)雅'
請(qǐng)先查閱函數(shù)spl_autoload_register文檔
其實(shí)composer也是利用這個(gè)函數(shù)來(lái)實(shí)現(xiàn)自動(dòng)加載的.
php代碼執(zhí)行時(shí), 如果遇到代碼里依賴(lài)了一個(gè)類(lèi), 而這個(gè)類(lèi)在當(dāng)前進(jìn)程中不存在時(shí), php 會(huì)按照加載器隊(duì)列順序調(diào)用通過(guò)spl_autoload_register函數(shù)注冊(cè)過(guò)的類(lèi)加載器. 直到某個(gè)加載器執(zhí)行完后, 這個(gè)被依賴(lài)的類(lèi)被加載進(jìn)當(dāng)前進(jìn)程空間, 或者所有加載器都執(zhí)行完這個(gè)類(lèi)仍不存在, 并拋出類(lèi)不存在的異常.
所以我們也可以利用spl_autoload_register函數(shù), 注冊(cè)一個(gè)加載器, 并使其在隊(duì)列里位于composer加載器之前. 當(dāng)php需要加載我們要改動(dòng)的第三方代碼包里的類(lèi)時(shí), 我們加載自己改好的php文件, 而不是vendor包里的php文件. 這樣就達(dá)到了覆蓋的目的.
煮個(gè)栗子:
我寫(xiě)了一個(gè)自動(dòng)搶餓了么最大外賣(mài)紅包swoole程序. 大概流程就是, 利用hanson/vbot 包監(jiān)聽(tīng)微信群里發(fā)送的紅包鏈接, 并把鏈接推送到紅包隊(duì)列, 然后有個(gè)進(jìn)程使用小號(hào)輪訓(xùn)餓了么接口, 等紅包的下一個(gè)就是最大時(shí), 用大號(hào)去領(lǐng), 就領(lǐng)到了, 但是有個(gè)問(wèn)題:
vbot 包有個(gè)message handler類(lèi), 里面有個(gè)listen方法. 這個(gè)方法里會(huì)調(diào)用微信網(wǎng)頁(yè)版的接口. 當(dāng)收到微信消息時(shí)會(huì)調(diào)用用戶(hù)的消息處理器, 并且此方法是while(true)循環(huán).所以一旦執(zhí)行l(wèi)isten方法, 整個(gè)進(jìn)程是會(huì)阻塞在這個(gè)方法里的, 就算用swoole的異步定時(shí)器也無(wú)力回天. 但是我又有個(gè)需求, 就是異步發(fā)送消息: 當(dāng)某個(gè)紅包的最大紅包來(lái)臨時(shí), 可以配置不自動(dòng)搶, 而是把鏈接轉(zhuǎn)發(fā)到一個(gè)'內(nèi)部群', 由群?jiǎn)T搶最大紅包. 所以我只好修改一下這個(gè)類(lèi)了, 把while(true)循環(huán)改成swoole的定時(shí)器

項(xiàng)目目錄結(jié)構(gòu)

注意到, overwrite文件夾, 就是我用來(lái)放覆蓋第三方代碼php文件的目錄
里面的autoload.php文件內(nèi)容:
<?php
spl_autoload_register(function ($cls) {
$map = [
'Hanson\Vbot\Core\MessageHandler' => __DIR__ . '/MessageHandler.php',
'Hanson\Vbot\Core\Server' => __DIR__ . '/Server.php',
];
if (isset($map[$cls])) {
echo $cls . ' loaded' . PHP_EOL;
include $map[$cls];
return true;
}
// 注意需要設(shè)置prepend參數(shù)為true
}, true, true);
項(xiàng)目的composer.json加載了這autoload.php:
{
"require": {
"hanson/vbot": "^2.0",
"symfony/debug": "^4.1"
},
"autoload": {
"psr-4": {
"App\\": "src/"
},
"files": ["src/overwrite/autoload.php"]
}
}
請(qǐng)自行體會(huì)