設定和使用自訂安裝程式#

概要#

有時,套件可能需要在安裝過程中執行額外動作,例如在預設的 供應商程式庫外安裝套件。

在這種情況下,您可以考慮建立一個自訂安裝程式來處理您的特定邏輯。

使用 Composer 2.1+ 的自訂安裝程式替代方案#

從 Composer 2.1 開始,Composer\InstalledVersions 類別具有一個 getInstalledPackagesByType 方法,讓您可以在執行階段找出已安裝哪些外掛程式/模組/擴充功能。

如果您正在建立新的應用程式,強烈建議使用此方法,而不是建立新的自訂安裝程式。此方法的優點是將所有供應商程式碼保留在供應商目錄中,並且不需要自訂安裝程式程式碼。

呼叫自訂安裝程式#

假設您的專案已經有針對特定模組的自訂安裝程式,那麼呼叫該安裝程式只需在您的套件檔案中定義正確的 類型 即可。

請參閱下一章節以取得如何建立自訂安裝程式的說明。

每個自訂安裝程式定義它將識別哪一個 類型 字串。識別後,它將完全覆寫預設安裝程式,而且只套用它自己的邏輯。

一個範例用例如下

phpDocumentor具有需要安裝在預設 /vendor 資料夾結構外部的範本。因此,他們選擇採用phpdocumentor-template 類型 並建立一個提供自訂安裝程式的外掛程式,將這些範本傳送到正確的資料夾。

這種範本套件的範例 composer.json 如下

{
    "name": "phpdocumentor/template-responsive",
    "type": "phpdocumentor-template",
    "require": {
        "phpdocumentor/template-installer-plugin": "*"
    }
}

重要提醒:為確保範本安裝程式在範本套件安裝時存在,範本套件應需要外掛程式套件。

建立安裝程式#

自訂安裝器定義為實作Composer\Installer\InstallerInterface介面的類別,通常會在 Composer 外掛程式中發行。

因此,基本安裝器外掛程式會由以下三個檔案組成:

  1. 套件檔案:composer.json
  2. 外掛程式類別,例如:My\Project\Composer\Plugin.php,其中包含實作Composer\Plugin\PluginInterface 的類別。
  3. 安裝器類別,例如:My\Project\Composer\Installer.php,其中包含實作Composer\Installer\InstallerInterface 的類別。

composer.json#

套件檔案與其他套件檔案相同,但有以下需求:

  1. 類型屬性必須為composer-plugin
  2. 額外屬性必須包含元素class,定義外掛程式的類別名稱(包括命名空間)。如果套件包含多個外掛程式,這可以是類別名稱的陣列。

範例

{
    "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() 方法中註冊自訂安裝器。

類別可以放在任何位置並具有任何名稱,只要它可以自動載入且與套件定義中的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 名稱,建議遵循格式:廠商-類型。例如:phpdocumentor-template

InstallerInterface 類別定義以下方法(請參閱原始碼以取得確實簽章)

  • supports(),在此您測試傳遞的type 是否與您為此安裝器宣告的名稱相符(請參閱範例)。
  • isInstalled(),判斷受支援套件是否已安裝。
  • install(),在此您可以決定安裝時需要執行的動作。
  • update(),在此您定義當使用更新參數呼叫 Composer 時所需的行為。
  • uninstall(),在此您可以決定當需要移除套件時需要執行的動作。
  • getInstallPath(),此方法應傳回套件要安裝到的絕對路徑。路徑 不得以斜線結尾。

範例

<?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-),並使用剩下的部分組成完全不同的安裝路徑。

使用此安裝程式安裝的所有套件,將被置於 /data/templates/<stripped name> 資料夾中,而非安裝在 /vendor

發現錯字嗎?這份文件中有錯誤的地方嗎?修正分叉