指令碼#
什麼是指令碼?#
以 Composer 的說法,指令碼可以是 PHP 回呼 (定義為靜態方法) 或任何命令列可執行指令。在 Composer 執行過程中,指令碼可用於執行套件的自訂程式碼或套件特定指令。
自 Composer 2.5 起,指令碼也可以是 Symfony Console 指令類別,讓您可以輕鬆執行它們,包含傳遞選項。不過,這不建議用於處理事件。
注意:只有在根套件的
composer.json
中定義的指令碼會被執行。如果根套件的相依性指定自己的指令碼,Composer 就不會執行這些額外的指令碼。
事件名稱#
Composer 會在其執行過程中引發以下命名的事件
指令事件#
- pre-install-cmd:在執行
install
指令且存在鎖定檔案之前發生。 - post-install-cmd:在執行
install
指令且存在鎖定檔案之後發生。 - pre-update-cmd:在執行
update
指令之前,或在沒有鎖定檔案的情況下執行install
指令之前發生。 - post-update-cmd:在執行
update
指令之後,或在沒有鎖定檔案的情況下執行install
指令之後發生。 - pre-status-cmd:在執行
status
指令之前發生。 - post-status-cmd:在執行
status
指令之後發生。 - pre-archive-cmd:在執行
archive
指令之前發生。 - post-archive-cmd:在執行
archive
指令之後發生。 - pre-autoload-dump:在自動載入器被傾印之前發生,發生的時機是在
install
/update
期間,或透過dump-autoload
指令。 - post-autoload-dump:自動載入程式傾印後,在
install
/update
期間,或透過dump-autoload
指令執行時所觸發。 - post-root-package-install:在 root 套件於
create-project
指令執行期間安裝後,所觸發(但其依賴項目尚未安裝之前)。 - post-create-project-cmd:在
create-project
指令執行後,所觸發。
安裝器事件#
- pre-operations-exec:在鎖檔安裝時安裝/升級/…運算執行前所觸發。需要串接此事件的插件必須以全域方式安裝,才能使用,否則在專案重新安裝時尚未載入。
套件事件#
- pre-package-install:在套件安裝前所觸發。
- post-package-install:在套件安裝後所觸發。
- pre-package-update:在套件更新前所觸發。
- post-package-update:在套件更新後所觸發。
- pre-package-uninstall:在套件解除安裝前所觸發。
- post-package-uninstall:在套件解除安裝後所觸發。
插件事件#
- init:在 Composer 執行個體初始化完畢後所觸發。
- command:在任何 Composer 指令於 CLI 上執行前所觸發。它提供你存取程式輸入和輸出物件。
- pre-file-download:在檔案下載前所觸發,允許你根據要下載的 URL,在下載檔案之前,調整
HttpDownloader
物件。 - post-file-download:在套件 dist 檔案下載後所觸發,並允許你在需要時,對檔案執行其他檢查。
- pre-command-run:在指令執行前所觸發,並允許你調整
InputInterface
物件的選項和引數,以調整指令行為。 - pre-pool-create:在套件 Pool 建立前所觸發,並讓你過濾將進入求解器的套件清單。
注意:Composer 沒有在
install
或update
前,假設你的依賴項狀態。因此,你不應該在pre-update-cmd
或pre-install-cmd
事件鉤中,指定需要 Composer 管理的依賴項的指令碼。如果你需要在install
或update
之前執行指令碼,請確保它們自我封閉在你的 root 套件內。
定義指令碼#
在 composer.json
中的根 JSON 物件應該有一個稱作 "scripts"
的屬性,其中包含命名事件對應的指令碼。事件的指令碼可以定義為字串(僅限於單一指令碼)或陣列(單一或多個指令碼)。
對於任何事件
- 在對應事件觸發時,指令碼依定義順序執行。
- 連結到單一事件的指令碼陣列,可以包含 PHP 回呼函式和命令列可執行指令碼。
- 包含已定義回呼的 PHP 類別和命令必須可以使用 Composer 的自動載入功能自動載入。
- 回呼只能從 psr-0、psr-4 和類別對應定義中自動載入類別。如果已定義的回呼仰賴在類別外部定義的函式,回呼會自行載入含有這些函式的檔案。
指令碼定義範例
{
"scripts": {
"post-update-cmd": "MyVendor\\MyClass::postUpdate",
"post-package-install": [
"MyVendor\\MyClass::postPackageInstall"
],
"post-install-cmd": [
"MyVendor\\MyClass::warmCache",
"phpunit -c app/"
],
"post-autoload-dump": [
"MyVendor\\MyClass::postAutoloadDump"
],
"post-create-project-cmd": [
"php -r \"copy('config/local-example.php', 'config/local.php');\""
]
}
}
使用先前的定義範例,以下是用來執行 PHP 回呼的類別 MyVendor\MyClass
<?php
namespace MyVendor;
use Composer\Script\Event;
use Composer\Installer\PackageEvent;
class MyClass
{
public static function postUpdate(Event $event)
{
$composer = $event->getComposer();
// do stuff
}
public static function postAutoloadDump(Event $event)
{
$vendorDir = $event->getComposer()->getConfig()->get('vendor-dir');
require $vendorDir . '/autoload.php';
some_function_from_an_autoloaded_file();
}
public static function postPackageInstall(PackageEvent $event)
{
$installedPackage = $event->getOperation()->getPackage();
// do stuff
}
public static function warmCache(Event $event)
{
// make cache toasty
}
}
注意:在執行 Composer install
或 update
命令期間,會將名為 COMPOSER_DEV_MODE
的變數新增到環境中。如果該命令以 --no-dev
旗標執行,這個變數會設為 0,否則會設為 1。這個變數在 dump-autoload
執行時也會提供,且會設為最後一次執行 install
或 update
時的設定值。
事件類別#
事件觸發後,PHP 回呼會收到 Composer\EventDispatcher\Event
物件。這個物件有一個 getName()
方法,可讓您擷取事件名稱。
根據指令碼類型,您會收到不同的事件子類別,這些子類別包含具有相關資料和關聯物件的各種取得器
- 基本類別:
Composer\EventDispatcher\Event
- 命令事件:
Composer\Script\Event
- 安裝程式事件:
Composer\Installer\InstallerEvent
- 套件事件:
Composer\Installer\PackageEvent
- 外掛程式事件
- init:
Composer\EventDispatcher\Event
- command:
Composer\Plugin\CommandEvent
- pre-file-download:
Composer\Plugin\PreFileDownloadEvent
- post-file-download:
Composer\Plugin\PostFileDownloadEvent
- init:
手動執行指令碼#
如果您想要手動執行某個事件的指令碼,其語法如下
php composer.phar run-script [--dev] [--no-dev] script
例如,composer run-script post-install-cmd
會執行任何已定義的 post-install-cmd 指令碼和 外掛程式。
您也可以透過附加上 --
字元後面接處理器引數的方式,向指令碼處理器提供額外的引數。例如,composer run-script post-install-cmd -- --check
會將 --check
傳遞給指令碼處理器。這些引數由 CLI 處理器接收為 CLI 參數,PHP 處理器可以用陣列形態透過 $event->getArguments()
來擷取。
撰寫自訂命令#
如果您新增不符合上述預先定義事件名稱的客製化指令碼,您可以透過 run-script 執行它們,也可以將它們當成原生 Composer 指令來執行。例如,以下定義的處理常式可以透過執行 composer test
執行
{
"scripts": {
"test": "phpunit",
"do-something": "MyVendor\\MyClass::doSomething"
"my-cmd": "MyVendor\\MyCommand"
}
}
類似於 run-script
指令,您可以為指令碼提供額外引數,例如,composer test -- --filter <pattern>
會將 --filter <pattern>
傳遞給 phpunit
指令碼。
透過 composer do-something arg
使用 PHP 方法,讓您能夠執行 static function doSomething(\Composer\Script\Event $event)
,而 arg
會在 $event->getArguments()
中可用。不過,這並不允許您輕鬆地以 --flags
形式傳遞自訂選項。
透過使用 symfony/console Command
類別,您可以更輕鬆地定義並存取引數和選項。
例如,使用以下指令,您只需呼叫 composer my-cmd --arbitrary-flag
即可,甚至不需要 --
分隔符號。為了被偵測為 symfony/console 指令,類別名稱必須以 Command
結尾並延伸 symfony 的 Command
類別。另外,請注意,這會使用 Composer 內建的 symfony/console 版本執行,而該版本可能與您在專案中需要的版本不符,並可能在 Composer 次要版本之間變更。如果您需要更高的安全性保證,您應該使用自己的二進位檔案,才能在獨立的程序中隔離執行自己的 symfony/console 版本。
<?php
namespace MyVendor;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class MyCommand extends Command
{
protected function configure(): void
{
$this->setDefinition([
new InputOption('arbitrary-flag', null, InputOption::VALUE_NONE, 'Example flag'),
new InputArgument('foo', InputArgument::OPTIONAL, 'Optional arg'),
]);
}
public function execute(InputInterface $input, OutputInterface $output): int
{
if ($input->getOption('arbitrary-flag')) {
$output->writeln('The flag was used');
}
return 0;
}
}
注意:在執行指令碼之前,Composer 的 bin-dir 會暫時推進到 PATH 環境變數的頂端,才能直接存取相依項目的二進位檔案。在此範例中,不論
phpunit
二進位檔案實際上位於vendor/bin/phpunit
或bin/phpunit
中,都將會被尋找並執行。
管理程序逾時#
雖然 Composer 並非用來管理 PHP 專案的長期執行程序及其他此類面向,但有時在自訂指令中停用程序逾時會很有幫助。此逾時的預設值為 300 秒,可以透過各種方式覆寫,具體取決於所需的效果
- 使用設定金鑰
process-timeout
為所有指令停用 - 使用環境變數
COMPOSER_PROCESS_TIMEOUT
為目前或未來呼叫 Composer 停用 - 針對特定呼叫,使用
run-script
指令的--timeout
標記 - 針對特定指令碼,使用靜態輔助程式。
若要直接在 composer.json 中使用靜態輔助程式停用特定指令碼的逾時
{
"scripts": {
"test": [
"Composer\\Config::disableProcessTimeout",
"phpunit"
]
}
}
若要停用特定專案上每個指令碼的逾時,您可以使用 composer.json 設定檔
{
"config": {
"process-timeout": 0
}
}
也可以設定全域環境變數,以停用目前終端機環境中所有後續指令碼的逾時
export COMPOSER_PROCESS_TIMEOUT=0
若要停用單一指令碼呼叫的逾時,您必須使用 run-script
composer 指令並指定 --timeout
參數
php composer.phar run-script --timeout=0 test
腳本參考#
為啟用腳本重複使用並避免重複,您可透過在指令名稱前加 @
,在其他指令中呼叫腳本
{
"scripts": {
"test": [
"@clearCache",
"phpunit"
],
"clearCache": "rm -rf cache/*"
}
}
您也可以參考腳本並傳遞新參數
{
"scripts": {
"tests": "phpunit",
"testsVerbose": "@tests -vvv"
}
}
呼叫 Composer 指令#
為呼叫 Composer 指令,您可以使用 @composer
,將自動解析為目前正在使用的 composer.phar
{
"scripts": {
"test": [
"@composer install",
"phpunit"
]
}
}
這項技術的限制是您無法持續呼叫多個 composer 指令,例如 @composer install && @composer foo
。您必須使用 JSON 指令陣列將它們區分開來。
執行 PHP 腳本#
若要執行 PHP 腳本,您可以使用 @php
,將自動解析為目前正在使用的 php 程序
{
"scripts": {
"test": [
"@php script.php",
"phpunit"
]
}
}
這項技術的限制是您無法持續呼叫多個指令,例如 @php install && @php foo
。您必須使用 JSON 指令陣列將它們區分開來。
您也可以呼叫 shell/bash 腳本,其使用路徑在 PHP 執行檔中可用,作為 PHP_BINARY
環境變數.
設定環境變數#
若要跨平台設定環境變數,您可以使用 @putenv
{
"scripts": {
"install-phpstan": [
"@putenv COMPOSER=phpstan-composer.json",
"@composer install --prefer-dist"
]
}
}
自訂說明#
您可以在 composer.json
中使用下列方式設定腳本自訂說明
{
"scripts-descriptions": {
"test": "Run all tests!"
}
}
說明用於 composer list
或 composer run -l
指令中,說明執行指令時腳本會做什麼。
注意事項:您只能設定自訂指令的自訂說明。
自訂別名#
在 Composer 2.7 中,您可以在 composer.json
中使用下列方式來設定自訂腳本別名
{
"scripts-aliases": {
"phpstan": ["stan", "analyze"]
}
}
別名提供替代性指令名稱。
注意事項:您只能設定自訂指令的自訂別名。
找到錯字嗎?此文件有任何錯誤嗎?Fork 並編輯!