- Описание задачи пользовательской установки в Composer
- Альтернатива пользовательским установщикам в Composer 2.1+
- Вызов пользовательского инсталлятора в Composer
- Создание инсталлятора для Composer
Описание задачи пользовательской установки в Composer
Иногда может возникнуть необходимость в том, чтобы при установке пакета в Composer требовались дополнительные действия, например, установка пакетов за пределами библиотеки поставщика vendor
по умолчанию.
В таких случаях можно рассмотреть возможность создания в Composer пользовательского установщика для обработки специфической логики.
Альтернатива пользовательским установщикам в Composer 2.1+
Начиная с версии Composer 2.1, класс Composer\InstalledVersions
имеет метод getInstalledPackagesByType
, который позволяет во время выполнения определить, какие плагины/модули/расширения установлены.
Настоятельно рекомендуется использовать этот метод вместо создания новых пользовательских программ установки, если вы создаете новое приложение. Преимущество этого метода в том, что весь код поставщика остается в каталоге поставщика vendor
и не требует создания пользовательского инсталлятора.
Вызов пользовательского инсталлятора для Composer
Предположим, что в вашем проекте уже есть пользовательский установщик для определенных модулей, тогда вызов этого установщика - это вопрос определения правильного type
в файле вашего пакета.
Инструкцию по созданию пользовательских инсталляторов смотрите в следующей главе.
Каждый пользовательский инсталлятор определяет, какой тип (type
) строки он будет распознавать. После распознавания он полностью отменяет установщик по умолчанию и применяет только свою собственную логику.
В качестве примера можно привести следующий случай:
phpDocumentor
имеет шаблоны (Templates), которые должны быть установлены вне стандартной структуры папок/vendor
. В связи с этим разработчики решили принять тип (type
)phpdocumentor-template
и создать плагин, предоставляющий Custom Installer для передачи этих шаблонов в нужную папку.
Пример composer.json такого пакета шаблонов выглядит следующим образом:
{
"name": "phpdocumentor/template-responsive",
"type": "phpdocumentor-template",
"require": {
"phpdocumentor/template-installer-plugin": "*"
}
}
ВАЖНО: Чтобы убедиться, что программа установки шаблонов присутствует в момент установки пакета шаблонов, пакеты шаблонов должны запрашивать пакет плагина.
Создание инсталлятора в Composer
Пользовательский установщик определяется как класс, который реализует интерфейс Composer\Installer\InstallerInterface
и обычно поставляется в Composer Plugin.
Базовый плагин установщика, таким образом, состоит из трех файлов:
- Файл пакета:
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
должен содержать элементclass
, определяющий имя класса плагина (включая namespace). Если пакет содержит несколько плагинов, это может быть массив имен классов.
Пример:
{
"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, например, в тестовом пакете.
Класс Plugin
Класс, определяющий плагин Composer, должен реализовать интерфейс Composer\Plugin\PluginInterface
. Затем он может зарегистрировать Custom Installer в своем методе 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
Класс, выполняющий пользовательскую установку, должен реализовать интерфейс Composer\Installer\InstallerInterface
(или дополнить другой установщик, реализующий этот интерфейс). Он определяет строку type
, как она будет распознаваться пакетами, которые будут использовать эту программу установки в методе supports()
.
ПРИМЕЧАНИЕ: Выбирайте имя для
type
внимательно, рекомендуется придерживаться формата:vendor-type
. Например:phpdocumentor-template
.
Класс InstallerInterface
определяет следующие методы (точные характеристики смотрите в исходнике):
supports()
, здесь проверяется, соответствует ли переданныйtype
тому имени, которое вы объявили для этого инсталлятора (см. пример ниже).isInstalled()
, определяет, установлен ли поддерживаемый пакет или нет.install()
, здесь можно определить действия, которые должны быть выполнены при установке.update()
, здесь определяется поведение, которое требуется при вызове Composer с аргументом update.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(
'Невозможно установить шаблон, '
.'шаблоны phpdocumentor всегда должны начинать свое имя пакета с '
.'"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/<stripped name>
.
Перевод с английского официальной документации Composer:
https://getcomposer.org/doc/articles/custom-installers.md
Заберите ссылку на статью к себе, чтобы потом легко её найти!
Раз уж досюда дочитали, то может может есть желание рассказать об этом месте своим друзьям, знакомым и просто мимо проходящим?
Не надо себя сдерживать! ;)