插件的设置和使用#
概要#
你可能希望用自己的代码来修改或扩展 Composer 的功能。例如,如果你的环境对 Composer 的行为提出了特殊要求,而这些要求不适用于大多数用户,或者如果你希望用大多数用户不希望的方式来完成某些 Composer 的功能。
在这种情况下,你可以考虑创建一个插件来处理你特定的逻辑。
创建插件#
插件是一个普通的 Composer 包,它将代码作为包的一部分提供,并且可能还依赖于其他包。
插件包#
包文件与任何其他包文件相同,但具有以下要求
- 该 type 属性必须为
composer-plugin
。 - 该 extra 属性必须包含一个元素
class
定义插件的类名(包括命名空间)。如果一个包包含多个插件,这可以是一个类名数组。 - 你必须需要一个名为
composer-plugin-api
的特殊包来定义你的插件兼容的哪个插件 API 版本。需要这个包实际上不包含任何额外的依赖项,它只是指定要使用的插件 API 的版本。
注意:在开发插件时,虽然不是必需的,但将
composer/composer
作为 require-dev 依赖项添加到 IDE 中,可以帮助你实现 Composer 类别的自动完成。
composer-plugin-api
的所需版本遵循与普通包相同的 规则。
当前的 Composer 插件 API 版本是 2.6.0
。
一个有效的插件 composer.json
文件示例(省略了自动加载部分,并且可选地将 composer/composer
作为 require-dev 依赖项添加到 IDE 中以实现自动完成)
{
"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_DEBUG_EVENTS=1 环境变量设置运行 Composer 命令,这可能会帮助你确定你正在寻找的事件。
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
的内部状态发生冲突的需要,通过为常见的插件需求提供明确的扩展点。
Capable Plugins 类必须实现 Composer\Plugin\Capable
接口并在 getCapabilities()
方法中声明它们的功能。此方法必须返回一个数组,其中键为 Composer 功能类名,而值为插件对该功能的自己的实现类名
<?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 组件。
手动运行插件#
可以通过 run-script
命令手动运行某个事件的插件。这与 手动运行脚本 的方式相同。
如果是其他类型的插件,最好使用 路径存储库 在测试项目中需要插件来测试它。如果你在本地开发并且想要频繁地进行测试,你可以确保路径存储库使用符号链接,因为更改会立即更新。否则,你将不得不每次都运行 rm -rf vendor && composer update
来重新安装/运行它。
使用插件#
插件包在安装后会自动加载,并且如果它们在当前项目的已安装包列表中找到,则在 Composer 启动时也会加载。此外,使用 Composer 全局命令安装在 COMPOSER_HOME
目录中的所有插件包,都会在加载本地项目插件之前加载。
你可以将
--no-plugins
选项传递给 Composer 命令以禁用所有已安装的插件。如果任何插件导致错误并且你希望更新或卸载它,这可能特别有用。
插件助手#
从 Composer 2 开始,由于 DownloaderInterface 有时可以返回 Promises,并且比以前拆分成了更多步骤,因此我们提供了一个 SyncHelper 来简化下载和安装包的操作。
插件额外属性#
可以使用插件的 composer.json 中的额外属性来解锁一些特殊的插件功能。
class#
参见上文了解 class 属性的工作原理和用法。
plugin-modifies-downloads#
一些特殊的插件需要在包下载之前更新包下载 URL。
从 Composer 2.0 开始,所有包都在安装之前下载。这意味着在第一次安装时,你的插件在下载发生时还没有安装,它没有机会及时更新 URL。
在你的 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 扩展安装程序 一起使用#
如果你的插件项目声明对 phpstan/extension-installer
的依赖关系,则会自动加载必要的配置文件。
替代手动安装#
要使用它,你的 Composer 插件项目需要一个 PHPStan 配置文件,该文件包含 phpstan/rules.neon
文件
includes:
- vendor/composer/composer/phpstan/rules.neon
// your remaining config..
发现错字?文档中有什么问题? 分叉并编辑 它!