Alle Composer-Pakete auf einmal auf die neueste Version aktualisieren

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.

Veröffentlicht von

Bernhard ist fest angestellter Webentwickler, entwickelt in seiner Freizeit Plugins, schreibt in seinem Blog über WordPress und andere Themen, treibt sich gerne bei den WP Meetups in Berlin und Potsdam herum und läuft nach Feierabend den ein oder anderen Halbmarathon.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert