有時(shí)需要在包的安裝過(guò)程中執(zhí)行其它的動(dòng)作,例如:將它安裝在默認(rèn)的 vendor
以外的其它目錄。
在這些情況下,你可以考慮創(chuàng)建一個(gè)自定義安裝程序來(lái)處理特定的邏輯。
假設(shè)你的項(xiàng)目已經(jīng)有了一個(gè)自定義的安裝模塊,那么如何根據(jù) 安裝類(lèi)型 正確調(diào)用你包文件中的安裝程序就成為了一個(gè)問(wèn)題。
參見(jiàn)見(jiàn)下一章,如何通過(guò)指令創(chuàng)建自定義安裝程序。
任何自定義安裝程序都要通過(guò) type 屬性來(lái)識(shí)別。一旦被確認(rèn),它將完全覆蓋默認(rèn)的安裝程序,并執(zhí)行自己的安裝邏輯。
一個(gè)實(shí)際用例:
phpDocumentor 的特殊模板需要安裝在 /vendor 以外的其它目錄中。 因此他們選擇 phpdocumentor-template
安裝類(lèi)型 并為此類(lèi)型創(chuàng)建了一個(gè)插件,以便將他們的模板發(fā)送到正確的目錄中。
在這樣一個(gè)模板包的例子中 composer.json 將使用以下設(shè)置:
{
"name": "phpdocumentor/template-responsive",
"type": "phpdocumentor-template",
"require": {
"phpdocumentor/template-installer-plugin": "*"
}
}
重要提示: 為了確保這個(gè)模板安裝程序在安裝模板包之前就已存在,模板包必須寫(xiě)入對(duì)此安裝程序包的依賴(lài)。
一個(gè)自定義安裝程序通常是以 Composer 插件的形式存在,并包含有一個(gè)類(lèi),它實(shí)現(xiàn)了 Composer\Installer\InstallerInterface
這個(gè)接口。
一個(gè)基本的安裝程序插件必須由3個(gè)文件組成:
My\Project\Composer\Plugin.php
,其中的類(lèi)必須實(shí)現(xiàn) Composer\Plugin\PluginInterface
接口。My\Project\Composer\Installer.php
,其中的類(lèi)必須實(shí)現(xiàn) Composer\Installer\InstallerInterface
接口。此處的包文件和普通資源包是相同的,但需要滿(mǎn)足以下條件:
composer-plugin
。class
元素,它定義了插件類(lèi)的名稱(chēng)(包含命名空間)。如果這個(gè)包有多個(gè)插件類(lèi),可以使用數(shù)組的形式進(jìn)行定義。實(shí)例:
{
"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.0"
}
}
這個(gè)類(lèi)定義了 Composer 的插件,它必須實(shí)現(xiàn) Composer\Plugin\PluginInterface
這個(gè)接口。它可以在 activate()
方法中注冊(cè)自定義安裝程序。
這個(gè)類(lèi)可以被放在任何位置、使用任何名字,只要能夠根據(jù) extra.class
中的定義被自動(dòng)加載即可。
實(shí)例:
<?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);
}
}
這個(gè)類(lèi)用于執(zhí)行自定義的安裝過(guò)程,它必須實(shí)現(xiàn) Composer\Installer\InstallerInterface
這個(gè)接口(或者繼承了另一個(gè)實(shí)現(xiàn)此接口的安裝程序類(lèi))。它將會(huì)對(duì)安裝類(lèi)型中定義的字符串執(zhí)行 supports()
方法驗(yàn)證,一旦通過(guò)就采用對(duì)應(yīng)的安裝程序。
注意: 請(qǐng)慎重選擇你的 安裝類(lèi)型 名稱(chēng),建議遵循這樣的格式:vendor-type
。例如:phpdocumentor-template
。
InstallerInterface 類(lèi)定義了以下方法(請(qǐng)查閱源碼以獲得更詳細(xì)的信息):
實(shí)例:
<?php
namespace phpDocumentor\Composer;
use Composer\Package\PackageInterface;
use Composer\Installer\LibraryInstaller;
class TemplateInstaller extends LibraryInstaller
{
/**
* {@inheritDoc}
*/
public function getPackageBasePath(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;
}
}
這個(gè)例子演示了,簡(jiǎn)單的繼承 Composer\Installer\LibraryInstaller
類(lèi)來(lái)剝離 phpdocumentor/template-
前綴,并用剩余的部分重新組裝了一個(gè)完全不同的安裝路徑。
并非安裝在 /vendor
目錄,任何使用這個(gè)安裝程序的資源包,將被放置在 /data/templates/<stripped name>
目錄中。
更多建議: