3.3. 自定义安装器
概述
有些时候,程序包可能需要在安装期间执行其他操作,例如在程序默认扩展库之外安装其他扩展包。
在这种情况下,你可以考虑创建自定义安装程序来处理你的特定安装逻辑。
调用自定义安装程序
假设你的程序已经有特定模块的自定义安装程序,那么调用这个安装程序就需要在扩展包文件中定义正确的安装 类型 。
关于如何创建自定义安装程序的说明,请参考下一章节
每个自定义安装程序都会定义它识别的安装 类型 。 如果执行识别成功,它讲完全覆盖默认的扩展包并执行它自有的逻辑。
下面是一个实例:
PHP文档中说明该功能需要除了在默认开发者提供的扩展包之外安装扩展,因此,他们会选择并采用
phpdocumentor-template
类型 并创建一个插件,提供自定义安装程序将这些扩展提交到指定的文件夹里。
下面就有一个 composer.json
模板文件:
{
"name": "phpdocumentor/template-responsive", //类名称
"type": "phpdocumentor-template", //类型
"require": {
"phpdocumentor/template-installer-plugin": "*" //扩展包名称及版本号
}
}
重要提示: 为了确保安装扩展包时验证模板文件存在,执行模板文件需要安装插件包。
创建安装程序
自定义安装程序定义为实现 Composer\Installer\InstallerInterface
的类,通常分步在 Composer 插件中。
因此,一个基本的安装程序插件将由三个文件组成:
- 包文件:composer.json
- Plugin 类,例如:
My\Project\Composer\Plugin.php
,包含一个实现Composer\Plugin\PluginInterface
的类。 - Installer 类,例如:
My\Project\Composer\Installer.php
,包含实现Composer\Installer\InstallerInterface
的类。
composer.json
包文件与任何其他包文件相同,但具有以下要求:
- type 属性必须是
composer-plugin
。 - extra 属性必须包含一个定义插件类名的元素类(包括命名空间)。如果包中包含多个插件,则可以是类名称数组。
例:
{
"name": "phpdocumentor/template-installer-plugin",
"type": "composer-plugin",
"license": "MIT",
"autoload": {
"psr-0": {"phpDocumentor\\Composer": "src/"}
},
"extra": {
"class": "phpDocumentor\\Composer\\TemplateInstallerPlugin"
},
"require": {
"composer-plugin-api": "^1.0"
},
"require-dev": {
"composer/composer": "^1.3"
}
}
上面的示例在其 require-dev 中有 Composer 本身,例如,它允许您在测试套件中使用 Composer 类。
插件类
定义 Composer 插件的类必须实现 Composer\Plugin\PluginInterface
. 然后,它可以在其 activate()
方法中注册 Custom Installer。.
该类可以放在任何位置并具有任何名称,只要它是可自动加载的并且与extra.class
包定义中的元素匹配即可。
例:
<?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\Installer\InstallerInterface
(或者扩展实现该接口的另一个安装程序)它定义了 type 字符串,因为它将在 supports()
方法中使用此安装程序的包进行识别。
注意:请仔细选择您的 type 名称,建议遵循以下格式:
vendor-type
。例如:phpdocumentor-template
。
InstallerInterface 类定义了以下方法(请参阅精确签名源):
- supports() ,在这里测试传递的 type 是否与您为此安装程序声明的名称匹配(请参阅示例)。
- isInstalled() ,确定是否安装了受支持的软件包。
- install(),在这里您可以确认安装时需要执行的操作。
- update(),在这里定义使用 update 参数调用 Composer 时所需的行为。
- uninstall(),在这里您可以确定需要移除包时需要执行的操作。
- getInstallPath(),这个方法应该返回要安装的包的位置,
相对于 composer.json 的位置
。
例如:
<?php
namespace phpDocumentor\Composer;
use Composer\Package\PackageInterface;
use Composer\Installer\LibraryInstaller;
class TemplateInstaller extends LibraryInstaller
{
/**
* {@inheritDoc}
*/
public function getInstallPath(PackageInterface $package)
{
$prefix = substr($package->getPrettyName(), 0, 23);
if ('phpdocumentor/template-' !== $prefix) {
throw new \InvalidArgumentException(
'Unable to install template, phpdocumentor templates '
.'should always start their package name with '
.'"phpdocumentor/template-"'
);
}
return 'data/templates/'.substr($package->getPrettyName(), 23);
}
/**
* {@inheritDoc}
*/
public function supports($packageType)
{
return 'phpdocumentor-template' === $packageType;
}
}
该示例演示了扩展 Composer\Installer\LibraryInstaller
类去除前缀(phpdocumentor/template-
)并使用剩下部分来组装完全不同的安装路径是非常简单的。
而不是安装在
/vendor中,任何使用此安装程序的程序包都将被放在
/data/templates/文件夹中
。