- Что такое скрипт в Composer?
- Название событий Composer
- Настройка сценариев Composer
- Классы событий Composer
- Запуск скриптов вручную в Composer
- Написание пользовательских команд Composer
- Управление временем ожидания процесса Composer
- Ссылки на скрипты Composer
- Вызов команд Composer
- Выполнение PHP-скриптов Composer
- Установка переменных окружения в Composer
- Пользовательские описания Composer
- Пользовательские алиасы Composer
Что такое скрипт в Composer?
В терминах Composer скрипт (сценарий) может быть как обратным вызовом PHP (определяемым как статический метод), так и любой исполняемой командой командной строки. Скрипты полезны для выполнения пользовательского кода пакета или специфических для пакета команд в процессе выполнения Composer.
Начиная с версии Composer 2.5 скрипты также могут быть классами Symfony Console Command, что позволяет легко запускать их, передавая параметры. Тем не менее, это не рекомендуется для обработки событий.
Примечание:
Выполняются только скрипты, определенные в composer.json корневого пакета. Если зависимость корневого пакета указывает свои собственные скрипты, Composer не будет выполнять дополнительные скрипты.
Название событий Composer.
В процессе выполнения 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
:- происходит после установки корневого пакета в ходе выполнения команды
create-project
(но до установки его зависимостей).
- происходит после установки корневого пакета в ходе выполнения команды
post-create-project-cmd
:- происходит после выполнения команды
create-project
.
- происходит после выполнения команды
События установщика Composer.
pre-operations-exec
:- происходит перед выполнением операций
install
/upgrade
/... при установке файла блокировки. Плагины, которым нужно подключиться к этому событию, должны быть установлены глобально, чтобы их можно было использовать, так как в противном случае они не будут загружены при свежей установке проекта.
- происходит перед выполнением операций
События пакета Composer.
pre-package-install
:- происходит до установки пакета.
post-package-install
:- происходит после установки пакета.
pre-package-update
:- происходит перед обновлением пакета.
post-package-update
:- происходит после обновления пакета.
pre-package-uninstall
:- происходит перед удалением пакета.
post-package-uninstall
:- происходит после удаления пакета.
События плагина Composer.
init
:- происходит после завершения инициализации экземпляра Composer.
command
:- происходит перед выполнением любой команды Composer в CLI. Она предоставляет доступ к объектам ввода и вывода программы.
pre-file-download
:- происходит перед загрузкой файлов и позволяет манипулировать объектом
HttpDownloader
перед загрузкой файлов на основе URL-адреса для загрузки.
- происходит перед загрузкой файлов и позволяет манипулировать объектом
post-file-download
:- происходит после загрузки файлов пакета дистрибутива и позволяет выполнить дополнительные проверки файла, если это необходимо.
pre-command-run
:- происходит перед выполнением команды и позволяет манипулировать параметрами и аргументами объекта
InputInterface
, чтобы изменить поведение команды.
- происходит перед выполнением команды и позволяет манипулировать параметрами и аргументами объекта
pre-pool-create
:- происходит перед созданием пула пакетов и позволяет отфильтровать список пакетов, которые попадут в Solver.
Примечание:
Composer не делает никаких предположений о состоянии ваших зависимостей перед командамиinstall
илиupdate
. Поэтому не следует указывать скрипты, требующие управляемых Composer зависимостей, в сценарияхpre-update-cmd
илиpre-install-cmd
. Если требуется выполнить скрипты перед процессамиinstall
илиupdate
, убедитесь, что они находятся в корневом пакете.
Настройка сценариев Composer.
Корневой объект JSON в composer.json
должен иметь свойство "scripts"
, которое содержит пары именованных событий и соответствующие им скрипты. Сценарии события могут быть заданы как строка (только для одного сценария) или массив (для одного или нескольких сценариев).
Для любого заданного события:
- Скрипты выполняются в порядке, определенном при наступлении соответствующего события.
- Массив скриптов, привязанных к одному событию, может содержать как обратные вызовы PHP, так и исполняемые команды командной строки.
- PHP-классы и команды, содержащие определенные обратные вызовы, должны быть автозагружаемыми с помощью функции автозагрузки Composer.
- Обратные вызовы могут автозагружать только классы из определений psr-0, psr-4 и classmap. Если определенный обратный вызов полагается на функции, определенные вне класса, то сам обратный вызов отвечает за загрузку файла, содержащего эти функции.
Пример использования определения сценария:
{
"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');\""
]
}
}
На примере предыдущего определения приведен класс MyVendor\MyClass
, который может быть использован для выполнения обратных вызовов PHP:
<?php
namespace MyVendor;
use Composer\Script\Event;
use Composer\Installer\PackageEvent;
class MyClass
{
public static function postUpdate(Event $event)
{
$composer = $event->getComposer();
// что-то сделать ещё
}
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();
// что-то сделать ещё
}
public static function warmCache(Event $event)
{
// сделать кэш вкусным
}
}
Примечание:
Во время выполнения командыinstall
илиupdate
Composer в окружение будет добавлена переменнаяCOMPOSER_DEV_MODE
. Если команда была запущена с флагом--no-dev
, эта переменная будет установлена в0
, в противном случае она будет установлена в1
. Переменная также доступна во время выполненияdump-autoload
, и она будет установлена в то же значение, в котором была запущена последняя командаinstall
илиupdate
.
Классы событий Composer.
Когда происходит событие, в качестве первого аргумента ваш обратный вызов PHP получает объект Composer\EventDispatcher\Event
. Этот объект имеет метод getName()
, который позволяет получить название события.
В зависимости от типа сценария вы получите различные подклассы событий, содержащие различные геттеры с соответствующими данными и связанными с ними объектами:
- Base class:
Composer\EventDispatcher\Event
- Command Events:
Composer\Script\Event
- Installer Events:
Composer\Installer\InstallerEvent
- Package Events:
Composer\Installer\PackageEvent
- Plugin Events:
init
:Composer\EventDispatcher\Event
command
:Composer\Plugin\CommandEvent
pre-file-download
:Composer\Plugin\PreFileDownloadEvent
post-file-download
:Composer\Plugin\PostFileDownloadEvent
Запуск скриптов вручную в Composer.
Если требуется запустить скрипты для события вручную, синтаксис будет следующим:
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, и могут быть получены как массив через $event->getArguments()
обработчиками PHP.
Написание пользовательских команд Composer.
Если добавляются пользовательские сценарии, которые не подходят ни под одно из предопределенных выше названий событий, их можно запустить с помощью 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
.
Использование метода PHP через composer do-something arg
позволяет выполнить статическую функцию doSomething(\Composer\Script\Event $event)
и arg
становится доступным в $event->getArguments()
. Однако это не позволяет с легкостью передавать пользовательские параметры в виде --flags
.
Используя класс Command
из symfony/console
, можно определить и получить доступ к аргументам и параметрам более легко.
Например, с командой показанной ниже, можно просто вызвать composer my-cmd --arbitrary-flag
без разделителя --
. Чтобы команды были распознаны как команды symfony/console
, имя класса должно заканчиваться на Command
и расширять класс Command
symfony. Также обратите внимание, что для запуска будет использоваться встроенная в 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;
}
}
Примечание:
Перед выполнением скриптовbin-dir
Composer временно помещается поверх переменной окружения PATH, чтобы двоичные файлы зависимостей были доступны напрямую. В данном примере неважно, находится ли двоичный файлphpunit
вvendor/bin/phpunit
илиbin/phpunit
, он будет найден и выполнен.
Управление временем ожидания процесса Composer.
Хотя Composer не предназначен для управления длительными процессами и другими подобными моментами в PHP-проектах, иногда бывает полезно отключить таймаут процесса в пользовательских командах. По умолчанию этот таймаут составляет 300 секунд и может быть переопределен различными способами в зависимости от требуемого эффекта:
- отключить его для всех команд с помощью config-ключа
process-timeout
, - отключить его для текущего или будущих вызовов Composer с помощью переменной окружения
COMPOSER_PROCESS_TIMEOUT
, - для конкретного вызова с помощью флага
--timeout
командыrun-script
, - с помощью статического помощника для отдельных скриптов.
Чтобы отключить таймаут для конкретных скриптов, используйте статический помощник непосредственно в 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
Ссылки на скрипты Composer.
Чтобы обеспечить повторное использование сценария и избежать дублирования, его можно вызвать из другого сценария, добавив к имени команды префикс @
:
{
"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-скриптов Composer.
Для выполнения PHP-скриптов можно использовать @php
, который автоматически переадресуется на тот процесс php, который используется в данный момент:
{
"scripts": {
"test": [
"@php script.php",
"phpunit"
]
}
}
Одно из ограничений заключается в том, что нельзя вызывать несколько команд подряд, например @php install && @php foo
. Их нужно разделить в JSON-массиве команд.
Также можно вызвать скрипт shell/bash, в котором путь к исполняемому файлу PHP будет доступен в качестве переменной окружения PHP_BINARY
.
Установка переменных окружения в Composer.
Чтобы установить переменную окружения кроссплатформенным способом, используется @putenv
:
{
"scripts": {
"install-phpstan": [
"@putenv COMPOSER=phpstan-composer.json",
"composer install --prefer-dist"
]
}
}
Пользовательские описания Composer.
В файле composer.json
можно задать пользовательские описания скриптов:
{
"scripts-descriptions": {
"test": "Запуск всех тестов!"
}
}
Описания используются в командах composer list
или composer run -l
для описания того, что делают скрипты при выполнении команды.
Примечание:
Настроить пользовательские описания можно только для пользовательских команд.
Пользовательские алиасы Composer.
В файле composer.json
можно задать пользовательские псевдонимы скриптов с помощью следующих параметров:
{
"scripts-aliases": {
"phpstan": ["stan", "analyze"]
}
}
Алиасы представляют собой альтернативные имена команд.
Примечание:
Установить пользовательские псевдонимы можно только для пользовательских команд.
Перевод с английского официальной документации Composer:
https://getcomposer.org/doc/articles/scripts.md
Заберите ссылку на статью к себе, чтобы потом легко её найти!
Раз уж досюда дочитали, то может может есть желание рассказать об этом месте своим друзьям, знакомым и просто мимо проходящим?
Не надо себя сдерживать! ;)