Wenn ihr in PHP programmiert, dann stehen die Chancen sehr hoch, dass ihr Composer zur Verwaltung der Abhängigkeiten verwendet. Irgendwann möchtet ihr die sicher einmal aktualisieren. Die Hauptversion, die ihr beim ersten Mal installiert habt, könnt ihr mit einem einzigen Befehl aktualisieren, allerdings nicht auf die nächste Hauptversion. Wenn ihr also viele Abhängigkeiten in einem alten Projekt habt, und dann testen wollt, ob diese auch in der neusten Version (mit einer aktuellen PHP-Version) funktionieren würden, müsst ihr normalerweise jedes Paket einzeln aktualisieren, indem ihr die Abhängigkeit erneut hinzufügt:
composer require wp-cli/mustangostang-spyc
composer require wp-cli/php-cli-tools
...
Jetzt könntet ihr natürlich einfach alle Paketnamen aus der composer.json
Datei kopieren, aber bei vielen Abhängigkeiten ist das recht aufwändig und man vergisst schnell mal einige. Daher habe ich nach einem Weg gesucht, alle Pakete in nur einem Befehl zu aktualisieren.
Alle Pakete auch einmal aktualisieren
Für diesen Blogbeitrag nehme ich das wp-cli/wp-cli Paket als Beispiel. Es hat eine ganz Reihe an Abhängigkeiten und Dev-Abhängigkeiten.
Alle Pakete als Liste erhalten
Im ersten Schritt müssen wir einen Befehl finden, der uns alle Composer-Pakete unseres Projekts als Liste liefert. Hierzu können wir den composer show
Befehl verwenden:
$ 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
In der Ausgabe gibt es zwei Abschnitte mit „requires“ und „requires (dev)“. Allerdings ist diese Ausgabe nur schwer nach den Namen der Pakete zu parsen. Glücklicherweise können wir die Ausgabe auch als JSON-Objekt erhalten, indem wir einfach das --format
Argument anhängen:
$ 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"
}
}
Jetzt müssen wir das JSON noch parsen. Auf meinem Linux-System steht mir hierzu der Befehl jq
zur Verfügung, mit dem man eine JSON-Datei oder Ausgabe parsen kann. Ich habe auch eine kleine Übersicht an nützlichen Argumenten gefunden, mit dem es mir dann möglich war, an den requires
Schlüssel zu gelangen:
$ 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"
}
Das ist schon mal toll! Aber wir brauchen lediglich die Namen der Pakete. Daher lesen wir im nächsten Schritt nur die Schlüssel des Objekts aus:
$ 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"
]
Um diese Liste nun in einem anderen Befehl verwenden zu können, brauchen wir sie in einer Zeile. Hierzu können wir add
verwenden:
$ composer show -s --format=json | jq '.requires | keys | add'
"ext-curlmustache/mustachephprmccue/requestssymfony/finderwp-cli/mustangostang-spycwp-cli/php-cli-tools"
Das ist nicht wirklich, was wir wollen, dann nach jeden Paketnamen sollte ein Leerzeichen kommen. Das erreichen wir mit 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 "
Jetzt haben wir es fast geschafft. Wir müssen nur noch die Anführungsstriche um den String entfernen, was uns mit dem -r
Parameter gelingt:
$ 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
Damit haben wir es also. Jetzt können wir das Ergebnis in einem Subbefehl verwenden und endlich mit einem einzelnen Befehl alle Abhängigkeiten aktualisieren:
$ 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
...
Das war’s! Wenn ihr in eurem Projekt auch Dev-Abhängigkeiten habt, dann müsst ihr noch einen zweiten Befehl ausführen, bei dem ihr dann an den composer
Befehl noch das --dev
Argument anhängt und nach devRequires
statt requires
filtert:
$ 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
...
Zusammenfassung
Ich hoffe, dass ich euch in diesem Beitrag erklären konnte, wie ihr mit Composer und einem weiteren Befehl eine solche Aufgabe in einem einzelnen Befehl erledigen könnt. Das hier sind noch einmal die zwei Befehle, die ihr vermutlich benötigt:
Für Abhängigkeiten:
composer require $(composer show -s --format=json | jq '.requires | keys | map(.+" ") | add' -r)
Für Dev-Abhängigkeiten:
composer require --dev $(composer show -s --format=json | jq '.devRequires | keys | map(.+" ") | add' -r)
Ich mag die Möglichkeiten von Kommandozeilen-Tools wirklich sehr, aber es ist manchmal nicht ganz leicht, solche Einzeiler zu finden. Nachdem ich einige Jahre nach einer Lösung für genau dieses Problem gesucht hatte, habe ich mir dann doch endlich mal die Zeit genommen, um eine Lösung zu finden, und zum Glück war ich erfolgreich dabei.