Composer 2: What's new and changed
Composer, PHP dependency manager was released about 8 years ago, and its second major version is just around the corner. Over the years, Composer received many new features, and kept up with PHP standards. Composer version 2 will be mostly compatible with your existing workflows, while bringing some more great new features.
Faster download times
One of the most noticeable changes would be its performance. Packages and meta data are downloaded parallel, which can significantly improve the time it takes to download packages.
Here is a comparison between composer v1.10.5 and v2 (40a35ab) to run composer require laravel/laravel
. The test was done on an empty cache, followed by a new test after the cache is primed. The test results are the average of 5 runs on consumer hardware.
Composer v2 was nearly 2 times faster to install
laravel/laravel
without caching.
This performance boost comes from parallel downloading of package meta data (which also new endpoints) and package zip files.
When curl is present, multiple packages/API calls will be downloaded all at the same time, reducing the overall download time. Furthermore, Composer v2 will make use of HTTP/2, and share TLS sessions, and DNS responses between HTTP requests to speed up downloads.
For Composer v1, hirak/prestissimo plugin brought these features for quite some time.
Partial offline support
You can prevent Composer v2 from attempting to make any network requests. This can come handy if you want to run benchmarks, or if your Internet connection is faulty. Composer v2 will try to install the packages provided a composer.lock
file exists and all packages and meta data are cached.
For this to work, set an environment variable COMPOSER_DISABLE_NETWORK
, with value 1
. Project composer.lock
file must be present for it to work.
Note that this will completely disable Composer from making network requests. It will not work as a fallback mechanism.
With the environment variable set, you can use composer install
command as you would do otherwise. Composer will show a warning that network is disabled, but it will continue anyway.
https://repo.packagist.org could not be fully loaded (Network disabled, request canceled: https://repo.packagist.org/packages.json), package information was loaded from the local cache and may be out of date
If a package is not available in cache, you will get an error:
The required git reference for ayesh/php-timer is not in cache and network is disabled, aborting
Run-time platform requirements check
Composer v2 will create an additional platform_check.php
file that checks the platform requirements (PHP version and loaded extensions) when the autoloader is loaded.
This is covered in length at Composer 2: Platform Check.
Dry-run support for require
and remove
commands
composer update
command has a --dry-run
option, that prevents composer from actually making any changes, but simply display the output in terminal.
Composer v2 brings --dry-run
option to composer require
and composer remove
commands too, which you can use to test package installation/removal without impacting actual project files.
Running as root
requires confirmation
Composer plugins and scripts can run arbitrary commands on the system. Running Composer as the root
user is often a bad idea because a malicious plugin/script can execute commands as root
too.
Prior to version 2, Composer raised a warning message when you try to run a command as root
:
Do not run Composer as root/super user! See https://getcomposer.org/root for details
With Composer version 2, you will get an interactive confirmation:
Do not run Composer as root/super user! See https://getcomposer.org/root for details
Continue as root/super user [yes]?
This confirmation will not appear if it is not supported on your terminal is not interactive. You can force this mode by passing the -n
/ --no-interaction
flag to the command. E.g.:
composer install --no-interaction
New repository metadata format
Composer v2 supports a new format for its repository meta data. Traditionally, Composer metadata files were large sharded JSON files, which required a few megabytes of downloads. The new format is light-weight, and repository maintainers provide URL endpoints for individual packages, which Composer can request and cache.
Packagist.org
already supports this format. If you are using other repositories, look for metadata-url
key in its packages.json
file.
Packagist returns this:
{
"packages": [],
"metadata-url": "/p2/%package%.json",
"provider-includes": {...}
...
}
When the metadata-url
is present, Composer v2 will use the new meta format endpoint. Composer v1 will continue to use the standard approach.
Canonical, filtering, and allow-only support for multiple repositories
Packagist.org is the default repository for Composer. But that doesn't mean you cannot use other repositories in your project.
Drupal has its official Composer repository, and WordPress has an unofficial repository, and your team/organization probably has one too.
When Composer looks up for a package, it queries all configured repositories, and finally, the default repository, which is packagist.org
(unless configured otherwise). With Composer version 2, you can further control how Composer should work with multiple repositories in a single project.
Repository Priorities
With Composer v2, Composer will look for packages in all repositories configured in the composer.json
files repositories
property in the order they are set. If a package is found in a repository, Composer will not look for that package in any other repositories further down the line.
Canonical Repositories
Composer v2 will consider all repositories to be canonical, and when a package is found in a repository, repositories with lower priorities cannot provide the same package, even if a newer version is available.
Canonical repositories help prevent accidentally installing packages from lower priority repositories (such as packagist.org
) when the package is found in private or package-specific repositories. Without canonical repositories, Composer might install a package from a lower priority repository if a newer version is found.
You can override this behavior by marking the repository as not canonical:
{
...
"repositories": [
{
"type": "composer",
"url": "https://example.org",
"canonical": false
}
]
...
}
Filtered Repositories
Composer v2 supports only
and exclude
directives in repository configuration. They tell Composer to only look for packages with an exact match or a pattern match in said repositories.
{
"repositories":[
{
"type":"composer",
"url":"https://packages.drupal.org/8",
"only": ["drupal/*"]
},
{
"type":"composer",
"url":"https://wpackagist.org",
"only": ["wpackagist-plugin/*", "wpackagist-theme/*"]
}
],
}
Composer will look for packages that match drupal/*
in the Drupal repo, and wpackagist-plugin/*
and wpackagist-theme/*
in WPackagist repos. If these repositories host packages for other vendor names, they will not be lookup up, nor used.
If these repositories do not host a package that match the only
repository, they will still be lookup up on other repositories further down the line.
You can specify specific package names in the only
directive as well.
You can also use the exclude
directive within a repository configuration to exclude specific packages or a pattern from being used from a particular repository.
{
"repositories":[
{
"type":"composer",
"url":"https://example.com",
"exclude": ["example/outdated-package"]
}
],
}
With settings above, all packages will be tried from the example.com
repo, except for example/outdated-package
. One use case would be a repository down the line hosting a newer version of the same package that you want to use instead of the one available at example.com
.
pear
repository is removed
About a decade ago, PHP had PEAR, or PHP Extension and Application Repository to install reusable packages. Composer naturally took over with its nicer user experience and vastly openness and ease of use. Composer v1 had support to install PEAR packages from PEAR channels by adding a custom repo with type pear
.
You can still install any PEAR packages that were hosted on php.net by simply installing using the pear/
vendor prefix. Support for custom PEAR repositories is removed in Composer v2.
Your existing PEAR packages with pear/
packages will likely continue to work, if they have moved to the pear/
vendor namespaces (which is the case for almost every maintained package).
--no-suggest
option is removed deprecated
Composer v2 deprecates the --no-suggest
option that was available in require
and update
commands.
You will get a notice saying this option is deprecated:
You are using the deprecated option "--no-suggest". It has no effect and will break in Composer 3.
A quick search at GitHub shows more than 400K repositories with YAML files (often used in CI configuration) with --no-suggest
option, which will throw the error above with Composer v2 v3.
This option was once removed, but then updated to emit a deprecation notice because several packages and their CI/CD workflows would have failed otherwise.
Lock, download, and install workflow improvements
Composer v2 has an improved workflow for package installation and updates.
During an installation or an update, all packages are locked first (updated in composer.lock
), then downloaded to cache (in parallel if possible). After all files are successfully downloaded, or when found in cache, Composer extracts them to the vendor-dir. This prevents broken/incomplete state in the vendor-dir in case the network fails in the middle of the process.
Furthermore, the vendor/composer/installed.json
file is refactored to use packages
property store all package information (as opposed to the root level in v1). For each package, its installation path is now stored in an install-path
relative to the installed.json
file. This file also stores whether the require-dev
packages were installed. Plugin maintains can make use of this information enhance their plugins.
composer-plugin-api
is now 2.0
This probably wouldn't surprise anyone. The plugin API provided by Composer v2 is marked 2.0
. This will prevent plugins from being installed if they require composer-plugin-api
with version constraint 1.0
.
If you maintain a Composer plugin, you will need to update this dependency to allow composer-plugin-api
versions 2.0
. It may be possible to support both versions from the same version, as long as all new interface methods are implemented.
Most notably, plugins must now implement PluginInterface::deactivate()
and PluginInterface::uninstall()
methods. You can discuss and take a look at other plugins implementations at this issue.
This section in Composer documentation has more information and a summary of changes.
--ignore-platform-req
option to ignore platform requirements selectively
A new command-line option --ignore-platform-req
is added to composer install
and composer update
commands. This option can be used to selectively ignore one or more platform requirements.
For example, to ignore PHP version required by root composer.json
or any of the dependencies, you can run:
composer install --ignore-platform-req php
This option is not to be confused with --ignore-platform-reqs
that ignores all platform requirements.
This feature is covered in length at How to install Composer packages ignore PHP and platform requirements
Try Composer v2 today!
You can try out Composer version 2 simply with composer self-update --snapshot
command. If you have plugins that do not work, they can be temporarily disabled with composer --no-plugins
.
If you find any bugs or have suggestions, create an issue or a pull-request.
Finally, let's take moment to appreciate Jordi, Nils, and other contributors immense efforts in bringing Composer to PHP. Composer changed PHP as we knew it last decade, made a lot of things we do with PHP today possible. Thank you!