設定和使用外掛程式#
綜合概述#
您可能希望變更或擴充 Composer 的功能來符合您自身的需要。例如,如果您的環境對 Composer 的行為提出特殊的要求,而這些要求並不適用於大多數使用者,或者您希望透過大多數使用者不希望的方式,使用 Composer 來達成某件事。
在這些情況下,您可以考慮建立外掛程式來處理您的特定邏輯。
建立外掛程式#
外掛程式是一個一般性的 Composer 套件,其程式碼與套件一同發貨,且可能也依賴其他套件。
外掛程式套件#
套件檔案與其他任何套件檔案都相同,但有以下要求
- 類型(type)屬性必須為
composer-plugin
。 - 額外屬性(extra)必須包含定義外掛程式類別名稱(包含命名空間)的
class
元素。如果套件包含多個外掛程式,這可以是類別名稱的陣列。 - 您必須需要名為
composer-plugin-api
的特殊套件來定義您的外掛程式與哪些 Plugin API 版本相容。需要此套件實際上並不會包含任何額外的相依關係,它只會指定要使用哪個版本的 Plugin API。
附註:在開發外掛程式時,雖然沒有要求,但加入一個對
composer/composer
的 require-dev 相依關係,以在 IDE 自動完成 Composer 類別,會很有幫助。
所需的 composer-plugin-api
版本遵循普通套件規範的相同 規範 。
目前的 Composer 外掛程式 API 版本為 2.6.0
。
有效的外掛程式 composer.json
檔案範例(省略自動載入部分,以及 IDE 自動完成的 composer/composer
選擇性 require-dev 依賴項)
{
"name": "my/plugin-package",
"type": "composer-plugin",
"require": {
"composer-plugin-api": "^2.0"
},
"require-dev": {
"composer/composer": "^2.0"
},
"extra": {
"class": "My\\Plugin"
}
}
外掛程式類別#
每個外掛程式都必須提供實作 Composer\Plugin\PluginInterface
的類別。外掛程式的 activate()
方法會在外掛程式載入後呼叫,並接收 Composer\Composer
的執行個體,以及 Composer\IO\IOInterface
的執行個體。透過使用這兩個物件,所有設定檔都可讀取,所有內部物件與狀態都可以依需求進行調整。
範例
<?php
namespace phpDocumentor\Composer;
use Composer\Composer;
use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface;
class TemplateInstallerPlugin implements PluginInterface
{
public function activate(Composer $composer, IOInterface $io)
{
$installer = new TemplateInstaller($io, $composer);
$composer->getInstallationManager()->addInstaller($installer);
}
}
事件處理常式#
此外,外掛程式可以實作 Composer\EventDispatcher\EventSubscriberInterface
,以便在外掛程式載入時自動將其事件處理常式註冊至 EventDispatcher
。
若要將方法註冊至事件,請實作 getSubscribedEvents()
方法,並讓它傳回陣列。陣列鍵必須是 事件名稱,而值是要呼叫的此類別中方法的名稱。
請注意:如果您不知道要監聽哪個事件,您可以執行 Composer 指令,設定 COMPOSER_DEBUG_EVENTS=1 環境變數,這可能有助於您找出您正在尋找的事件。
public static function getSubscribedEvents()
{
return array(
'post-autoload-dump' => 'methodToBeCalled',
// ^ event name ^ ^ method name ^
);
}
預設情況下,事件處理常式的優先順序設定為 0。可以透過附加一個元組來變更優先順序,其中第一個值和以前一樣是方法名稱,而第二個值是一個代表優先順序的整數。較高的整數代表較高的優先順序。優先順序 2 會在優先順序 1 之前呼叫,依此類推。
public static function getSubscribedEvents()
{
return array(
// Will be called before events with priority 0
'post-autoload-dump' => array('methodToBeCalled', 1)
);
}
如果應該呼叫多個方法,則可以將元組陣列附加到每個事件。元組不需要包含優先順序。如果省略,預設會為 0。
public static function getSubscribedEvents()
{
return array(
'post-autoload-dump' => array(
array('methodToBeCalled' ), // Priority defaults to 0
array('someOtherMethodName', 1), // This fires first
)
);
}
以下是完整的範例
<?php
namespace Naderman\Composer\AWS;
use Composer\Composer;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface;
use Composer\Plugin\PluginEvents;
use Composer\Plugin\PreFileDownloadEvent;
class AwsPlugin implements PluginInterface, EventSubscriberInterface
{
protected $composer;
protected $io;
public function activate(Composer $composer, IOInterface $io)
{
$this->composer = $composer;
$this->io = $io;
}
public function deactivate(Composer $composer, IOInterface $io)
{
}
public function uninstall(Composer $composer, IOInterface $io)
{
}
public static function getSubscribedEvents()
{
return array(
PluginEvents::PRE_FILE_DOWNLOAD => array(
array('onPreFileDownload', 0)
),
);
}
public function onPreFileDownload(PreFileDownloadEvent $event)
{
$protocol = parse_url($event->getProcessedUrl(), PHP_URL_SCHEME);
if ($protocol === 's3') {
// ...
}
}
}
外掛程式功能#
Composer 定義了一組外掛程式可以實作的標準功能。其目標是讓外掛程式生態系更穩定,因為它減少了對 Composer\Composer
內部狀態進行作業的需求,透過提供常見外掛程式需求的明確延伸點。
具備能力的 Plugins 類別必須實作 Composer\Plugin\Capable
介面,並在 getCapabilities()
方法中宣告其能力。此方法必須傳回一個陣列,其中 *key* 作為 Composer Capability 類別名稱,而 *value* 作為該能力的 Plugin 自身實作類別名稱
<?php
namespace My\Composer;
use Composer\Composer;
use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface;
use Composer\Plugin\Capable;
class Plugin implements PluginInterface, Capable
{
public function activate(Composer $composer, IOInterface $io)
{
}
public function getCapabilities()
{
return array(
'Composer\Plugin\Capability\CommandProvider' => 'My\Composer\CommandProvider',
);
}
}
命令提供者#
Composer\Plugin\Capability\CommandProvider
能力允許為 Composer 註冊其他命令
<?php
namespace My\Composer;
use Composer\Plugin\Capability\CommandProvider as CommandProviderCapability;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Composer\Command\BaseCommand;
class CommandProvider implements CommandProviderCapability
{
public function getCommands()
{
return array(new Command);
}
}
class Command extends BaseCommand
{
protected function configure(): void
{
$this->setName('custom-plugin-command');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$output->writeln('Executing');
return 0;
}
}
現在 custom-plugin-command
可與 Composer 命令並排使用。
Composer 命令基於 Symfony Console Component。
手動執行 plugins#
可以使用 run-script
命令手動執行事件的 Plugins。這與 手動執行腳本 的方式相同。
如果是其他類型的 plugin,測試它的最佳方式可能是使用 路徑儲存庫 來要求測試專案中的 plugin。如果您在本地進行開發,並想要頻繁測試,您可以確保路徑儲存庫使用符號連結,因為變更會立即更新。否則,您必須在每次您想要安裝/重新執行它時執行 rm -rf vendor && composer update
。
使用 Plugins#
一安裝 Plugin 套件,就會自動載入,而如果它們是在目前的專案已安裝套件清單中找到的,則當 Composer 開始啟動時會載入。此外,使用 Composer 全域命令安裝在 COMPOSER_HOME
目錄中的所有 Plugin 套件都會在載入本機專案 Plugin 套件之前載入。
您可以將
--no-plugins
選項傳遞給 Composer 命令,以停用所有已安裝的 plugin。如果任何 plugin 造成錯誤,而您想要更新或解除安裝它時,這可能特別有用。
Plugin 幫手#
由於在 Composer 2 中,DownloaderInterface
有時可能會傳回 Promises,並且已分為比以前更多的步驟,因此我們提供一個 SyncHelper,以簡化下載和安裝套件。
Plugin Extra 屬性#
在 plugin 的 composer.json 中使用 extra 屬性,可以解鎖一些特殊的 plugin 能力。
class#
請參閱上方的內容,以取得 class 屬性的說明,以及它是如何運作的。
plugin-modifies-downloads#
有些特殊 plugin 需要在套件下載前更新套件下載網址。
自 Composer 2.0 起,所有套件在安裝前皆會先下載。這表示在第一次安裝時,當下載發生時外掛程式尚未安裝,且沒有機會即時更新網址。
在 composer.json 中指定 {"extra": {"plugin-modifies-downloads": true}}
會向 Composer 暗示應該先單獨安裝外掛程式,然後再繼續下載其他套件。不過,這會稍微拖慢整體安裝過程的速度,因此如果外掛程式並非必要,請勿使用此選項。
plugin-modifies-install-path#
有些特殊的外掛程式會修改套件的安裝路徑。
自 Composer 2.2.9 起,您可以在 composer.json 中指定 {"extra": {"plugin-modifies-install-path": true}}
,讓 Composer 知道應該儘早啟動外掛程式,以防止 Composer 假設套件安裝在實際上不同的位置而產生負面影響。
plugin-optional#
由於 Composer 外掛程式可用於執行對安裝運作中的應用程式而言有必要的動作,例如修改檔案儲存的路徑,無意間略過必要的的外掛程式可能會導致應用程式損毀。因此,在非互動模式下,如果新的外掛程式未列在 "allow-plugins" 中,Composer 便會失敗,以強迫使用者決定是否要執行外掛程式,避免無聲失敗。
自 Composer 2.5.3 起,您可以在外掛程式中使用設定 {"extra": {"plugin-optional": true}}
,讓 Composer 知道略過外掛程式不會造成災難性的後果,且如果外掛程式尚未列在 "allow-plugins" 中,它可以在非互動模式下安全地關閉。Composer 的下次互動執行仍會提示使用者選擇是否要啟用或關閉外掛程式。
外掛程式自動載入#
因為 Composer 在執行時期載入外掛程式,且為了確保依賴其他套件的外掛程式可以正確運作,會在每次載入外掛程式時建立一個執行時期自動載入程式。那個自動載入程式只組態為載入外掛程式的依賴項,因此您可能無法存取所有已安裝的套件。
靜態分析支援#
自 Composer 2.3.7 起,我們提供了一個 phpstan/rules.neon
PHPStan 組態檔,這會在處理 Composer 外掛程式時提供額外的錯誤檢查。
與 PHPStan Extension Installer 搭配使用#
當您的外掛程式專案宣告對 phpstan/extension-installer
的依賴時,必要的組態檔會自動載入。
另類手動安裝#
要使用這個功能,您的 Composer 外掛程式專案需要一個 PHPStan 組態檔,其中包含 phpstan/rules.neon
檔案。
includes:
- vendor/composer/composer/phpstan/rules.neon
// your remaining config..
發現錯字?此文件中有些錯誤?修改它!