If you code in PHP, changes are very high that you are using composer to manage your dependencies. At one point, you will add a dependency. The version you’ve first installed can be updated with a single command, but it won’t update to a new major version. If you have a lot of dependencies in an old project, and you want to try, if all the newest versions of them would work (with a current PHP version), you would usually have to update every package separately, by adding it as a dependency again:
composer require wp-cli/mustangostang-spyc
composer require wp-cli/php-cli-tools
...
Now you could just copy/paste every package name from your composer.json
file, but for many dependencies, that’s quite a task, and you might miss some. So I was searching for a way to do it in just one command.
Updating all packages at once
For this blog post, I will use the wp-cli/wp-cli package as an example. It has a number of required and dev-required dependencies.
Getting all packages as a list
The first step is to find a command that gives us a list of all composer packages used in the project. We can use the composer show
command for this:
$ composer show -s
name : wp-cli/wp-cli
descrip. : WP-CLI framework
keywords : cli, wordpress
versions : * 2.7.x-dev
type : library
license : MIT License (MIT) (OSI approved) https://spdx.org/licenses/MIT.html#licenseText
homepage : https://wp-cli.org
source : [] a5336122dc45533215ece08745aead08af75d781
dist : [] a5336122dc45533215ece08745aead08af75d781
path :
names : wp-cli/wp-cli
support
issues : https://github.com/wp-cli/wp-cli/issues
source : https://github.com/wp-cli/wp-cli
docs : https://make.wordpress.org/cli/handbook/
autoload
psr-0
WP_CLI\ => php/
classmap
php/class-wp-cli.php, php/class-wp-cli-command.php
requires
php ^5.6 || ^7.0 || ^8.0
ext-curl *
mustache/mustache ^2.14.1
rmccue/requests ^1.8
symfony/finder >2.7
wp-cli/mustangostang-spyc ^0.6.3
wp-cli/php-cli-tools ~0.11.2
requires (dev)
roave/security-advisories dev-latest
wp-cli/db-command ^1.3 || ^2
wp-cli/entity-command ^1.2 || ^2
wp-cli/extension-command ^1.1 || ^2
wp-cli/package-command ^1 || ^2
wp-cli/wp-cli-tests ^3.1.6
suggests
ext-readline Include for a better --prompt implementation
ext-zip Needed to support extraction of ZIP archives when doing downloads or updates
Here you’ll find sections with the “requires” and “requires (dev)”. But this output is rather hard to parse for the names only. Fortunately, you can get the output as a JSON object as well, by adding the --format
argument:
$ composer show -s --format=json
{
"name": "wp-cli/wp-cli",
"description": "WP-CLI framework",
"keywords": [
"cli",
"wordpress"
],
"type": "library",
"homepage": "https://wp-cli.org",
"names": [
"wp-cli/wp-cli"
],
"versions": [
"2.7.x-dev"
],
"licenses": [
{
"name": "MIT License",
"osi": "MIT",
"url": "https://spdx.org/licenses/MIT.html#licenseText"
}
],
"source": {
"type": "",
"url": "",
"reference": "a5336122dc45533215ece08745aead08af75d781"
},
"dist": {
"type": "",
"url": "",
"reference": "a5336122dc45533215ece08745aead08af75d781"
},
"suggests": {
"ext-readline": "Include for a better --prompt implementation",
"ext-zip": "Needed to support extraction of ZIP archives when doing downloads or updates"
},
"support": {
"issues": "https://github.com/wp-cli/wp-cli/issues",
"source": "https://github.com/wp-cli/wp-cli",
"docs": "https://make.wordpress.org/cli/handbook/"
},
"autoload": {
"psr-0": {
"WP_CLI\\": "php/"
},
"classmap": [
"php/class-wp-cli.php",
"php/class-wp-cli-command.php"
]
},
"requires": {
"php": "^5.6 || ^7.0 || ^8.0",
"ext-curl": "*",
"mustache/mustache": "^2.14.1",
"rmccue/requests": "^1.8",
"symfony/finder": ">2.7",
"wp-cli/mustangostang-spyc": "^0.6.3",
"wp-cli/php-cli-tools": "~0.11.2"
},
"devRequires": {
"roave/security-advisories": "dev-latest",
"wp-cli/db-command": "^1.3 || ^2",
"wp-cli/entity-command": "^1.2 || ^2",
"wp-cli/extension-command": "^1.1 || ^2",
"wp-cli/package-command": "^1 || ^2",
"wp-cli/wp-cli-tests": "^3.1.6"
}
}
Now we need to parse the JSON. On my Linux system, I had the jq
command available, which allows you to parse a JSON file or output. I’ve found a nice cheat sheet with some useful argument and was able to just the get the requires
key:
$ composer show -s --format=json | jq '.requires'
{
"php": "^5.6 || ^7.0 || ^8.0",
"ext-curl": "*",
"mustache/mustache": "^2.14.1",
"rmccue/requests": "^1.8",
"symfony/finder": ">2.7",
"wp-cli/mustangostang-spyc": "^0.6.3",
"wp-cli/php-cli-tools": "~0.11.2"
}
This is great! But we only need the names of the packages, so in the next step, we get the object keys:
$ composer show -s --format=json | jq '.requires | keys'
[
"ext-curl",
"mustache/mustache",
"php",
"rmccue/requests",
"symfony/finder",
"wp-cli/mustangostang-spyc",
"wp-cli/php-cli-tools"
]
In order to use it in another command, we usually want the names in a single line, so we use add
to achieve this:
$ composer show -s --format=json | jq '.requires | keys | add'
"ext-curlmustache/mustachephprmccue/requestssymfony/finderwp-cli/mustangostang-spycwp-cli/php-cli-tools"
Not really what we want. We need a space after every package name. We can add it with map
:
$ composer show -s --format=json | jq '.requires | keys | map(.+" ") | add'
"ext-curl mustache/mustache php rmccue/requests symfony/finder wp-cli/mustangostang-spyc wp-cli/php-cli-tools "
We are almost there, we just need to remove the quotes around the string with the -r
argument:
$ composer show -s --format=json | jq '.requires | keys | map(.+" ") | add' -r
ext-curl mustache/mustache php rmccue/requests symfony/finder wp-cli/mustangostang-spyc wp-cli/php-cli-tools
And there we have it. Now we can put it into a sub command and finally update all required dependencies at once:
$ composer require $(composer show -s --format=json | jq '.requires | keys | map(.+" ") | add' -r)
Using version * for ext-curl
Info from https://repo.packagist.org: #StandWithUkraine
Using version ^2.14 for mustache/mustache
Using version ^7.4 for php
Using version ^2.0 for rmccue/requests
Using version ^5.4 for symfony/finder
Using version ^0.6.3 for wp-cli/mustangostang-spyc
Using version ^0.11.15 for wp-cli/php-cli-tools
./composer.json has been updated
...
That it! If your project also have dev requirements, you’ll need to run a second command updating them as well by adding --dev
to the composer
command and using devRequires
instead of requires
in the filter:
$ composer require --dev $(composer show -s --format=json | jq '.devRequires | keys | map(.+" ") | add' -r)
Using version dev-latest for roave/security-advisories
Using version ^2.0 for wp-cli/db-command
Using version ^2.2 for wp-cli/entity-command
Using version ^2.1 for wp-cli/extension-command
Using version ^2.2 for wp-cli/package-command
Using version ^3.1 for wp-cli/wp-cli-tests
./composer.json has been updated
...
Summary
I hope this blog post explained, how you can use composer and another command to get a task like this done in a single command. These are the two commands again you will probably need:
For required packages:
composer require $(composer show -s --format=json | jq '.requires | keys | map(.+" ") | add' -r)
For development packages:
composer require --dev $(composer show -s --format=json | jq '.devRequires | keys | map(.+" ") | add' -r)
I really like the power of command line tools, but finding a one-liner is sometimes a bit more tricky. After searching for a solution to this very problem, I finally took the time to come up with something, and fortunately I’ve found a solution.
Hey Bernhard. I found this useful and interesting. Thanks – Grant in Australia