May 25, 2021 Composer
Sometimes other actions need to be performed during the installation of the package, such as installing it in a
vendor
than the default vendor.
In these cases, you may want to consider creating a custom installer to handle specific logic.
Assuming that your project already has a custom installation module, how to call the installer in your package file correctly depending on the installation type becomes a problem.
See the next chapter on how to create a custom installer with instructions.
Any custom installer is recognized by the type property. Once confirmed, it completely overrides the default installer and executes its own installation logic.
An actual use case:
The special template for phpDocumentor needs to be installed in a directory other than /vendor.
So they chose
phpdocumentor-template
and created a plug-in for that type to send their template to the correct directory.
In an example of such a template package, composer.json will use the following settings:
{
"name": "phpdocumentor/template-responsive",
"type": "phpdocumentor-template",
"require": {
"phpdocumentor/template-installer-plugin": "*"
}
}
Important: To ensure that this template installer exists before the template package is installed, the template package must be written to rely on this installation package.
A custom installer usually exists as a Composer plug-in and contains a class that implements the interface of
Composer\Installer\InstallerInterface
A basic installer plug-in must consist of 3 files:
My\Project\Composer\Plugin.php
where the class must implement
Composer\Plugin\PluginInterface
interface.
My\Project\Composer\Installer.php
which must implement
Composer\Installer\InstallerInterface
interface.
The package files here are the same as the normal resource pack, but the following conditions apply:
composer-plugin
class
element, which defines the name of the plug-in class, including the namespace.
If the package has more than one plug-in class, you can define it in the form of an array.
Instance:
{
"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"
}
}
This class defines The Composer's plug-in, which
Composer\Plugin\PluginInterface
It can
activate()
in the activate() method.
This class can be placed anywhere, using any name, as long as it can be .class as defined in
extra.class
Instance:
<?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);
}
}
This class is used to perform a custom installation process, and it must implement the interface of
Composer\Installer\InstallerInterface
inherit another installer class that implements this interface).
It
supports()
method validation on the string defined in the installation type, and once passed, the corresponding installer is used.
Note: Choose
your installation type name
carefully,
and it is recommended to follow this format:
vendor-type
For example:
phpdocumentor-template
.
The Installer International class defines the following methods (see source code for more detailed information):
Instance:
<?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;
}
}
This example demonstrates that simply
Composer\Installer\LibraryInstaller
to
phpdocumentor/template-
a completely different installation path with the rest.
Not
/vendor
directory, any resource pack that uses this installer will be placed in the
/data/templates/<stripped name>
directory.