RootRifs
Zurueck zur Uebersicht
27.04.2026 10:00 RootRifs

Versionsangaben in der composer.json: Syntax, Bedeutung und Best Practices

Was bedeuten ^, ~, *, Bereiche, dev-Versionen und Stability-Flags in der composer.json? Dieser Leitfaden erklärt die Syntax von Composer-Versionsangaben verständlich, praxisnah und mit passenden Codebeispielen.

Versionsangaben in der composer.json: Syntax, Bedeutung und Best Practices
TL;DR

Die Versionsangaben in der composer.json entscheiden darüber, welche Paketversionen Composer installieren oder aktualisieren darf. Besonders wichtig sind Operatoren wie ^ und ~, aber auch Wildcards, Versionsbereiche und Stability-Flags. In den meisten produktiven PHP-Projekten ist ^ die sinnvollste Standardwahl, weil Sicherheits- und Bugfix-Updates möglich bleiben, ohne direkt in die nächste Major-Version zu springen.

Warum Versionsangaben in Composer so wichtig sind

Wer regelmäßig mit PHP arbeitet, kommt an Composer nicht vorbei. Spätestens beim Blick in die composer.json taucht dann die Frage auf: Was genau bedeutet eigentlich ^11.0, ~2.8 oder 6.4.*?

Genau diese Angaben steuern, wie flexibel dein Projekt mit Abhängigkeiten umgeht. Sind sie zu eng, bleiben wichtige Updates aus. Sind sie zu weit gefasst, kann es passieren, dass beim nächsten Update plötzlich inkompatible Änderungen einziehen.

Deshalb lohnt es sich, die Syntax von Composer-Versionsangaben sauber zu verstehen. Nicht nur theoretisch, sondern mit Blick auf echte Projekte, Wartbarkeit und sichere Updates im Alltag.

So sehen Versionsangaben in der composer.json aus

Abhängigkeiten stehen in Composer in der Regel im Bereich require oder require-dev. Rechts neben dem Paketnamen steht die Versionsregel.

{
    "require": {
        "laravel/framework": "^11.0",
        "guzzlehttp/guzzle": "~7.8",
        "symfony/console": "6.4.*"
    }
}

Composer sucht dann eine reale Paketversion, die zu dieser Regel passt. Welche Version am Ende tatsächlich installiert wird, landet anschließend in der composer.lock.

Exakte Versionen

Die einfachste Form ist eine feste Versionsnummer.

{
    "require": {
        "monolog/monolog": "3.6.0"
    }
}

Damit wird genau diese Version akzeptiert, sonst nichts. Das kann in Ausnahmefällen sinnvoll sein, ist für normale Anwendungen aber oft zu starr. Selbst kleine Bugfixes oder Security-Updates werden dadurch blockiert, solange du die Angabe nicht manuell änderst.

Was bedeutet ^ in der composer.json?

Der Caret-Operator ^ ist die gebräuchlichste Form für Composer Version Constraints. Er erlaubt kompatible Updates innerhalb derselben Major-Version.

{
    "require": {
        "laravel/framework": "^11.0"
    }
}

Praktisch heißt das:

  • ^11.0 erlaubt Versionen ab 11.0.0, aber kleiner als 12.0.0
  • ^2.3 erlaubt Versionen ab 2.3.0, aber kleiner als 3.0.0
  • ^0.3 erlaubt Versionen ab 0.3.0, aber kleiner als 0.4.0

Der letzte Punkt ist wichtig: Bei Versionen kleiner 1.0 ist Composer vorsichtiger, weil dort schon kleinere Sprünge oft nicht mehr als stabil kompatibel gelten.

Für die meisten produktiven Projekte ist ^ die beste Standardlösung. Sie hält dein Projekt updatefähig, ohne Major-Upgrades ungeprüft hereinzulassen.

Was bedeutet ~ in Composer?

Die Tilde ~ wirkt ähnlich, ist aber meist etwas enger gefasst. Sie eignet sich dann, wenn du Updates zulassen willst, aber den Rahmen etwas strikter setzen möchtest.

{
    "require": {
        "guzzlehttp/guzzle": "~7.8"
    }
}

Beispiele dazu:

  • ~7.8 erlaubt Versionen ab 7.8.0 bis kleiner 8.0.0
  • ~7.8.2 erlaubt Versionen ab 7.8.2 bis kleiner 7.9.0

Der Unterschied zu ^ fällt vor allem dann auf, wenn du sehr genau steuern willst, wie weit Minor- oder Patch-Updates gehen dürfen.

Wildcards mit *

Composer unterstützt auch Wildcards. Damit lassen sich ganze Versionsmuster freigeben.

{
    "require": {
        "symfony/console": "6.4.*"
    }
}

Das bedeutet zum Beispiel:

  • 6.4.* erlaubt alle Versionen der Reihe 6.4.x
  • 6.* erlaubt alle Versionen innerhalb der 6er-Hauptversion

Solche Angaben funktionieren, wirken in vielen Teams aber etwas unschärfer als ^6.4 oder ~6.4. Deshalb greifen viele Projekte lieber zu den expliziteren Operatoren.

Versionsbereiche und Vergleichsoperatoren

Wenn du es ganz präzise brauchst, kannst du mit Vergleichsoperatoren arbeiten.

{
    "require": {
        "doctrine/dbal": ">=3.7 <4.0"
    }
}

Übliche Operatoren sind:

  • > größer als
  • >= größer oder gleich
  • < kleiner als
  • <= kleiner oder gleich
  • != ungleich

Das ist flexibel, aber auch fehleranfälliger, wenn Regeln im Team später schnell verstanden werden sollen. Für typische Anwendungen ist ^ oft die lesbarere Wahl.

Mehrere erlaubte Versionszweige

Composer kann auch mehrere zulässige Bereiche mit || kombinieren. Das sieht man vor allem bei Bibliotheken, die mehrere größere Framework-Versionen unterstützen.

{
    "require": {
        "vendor/paket": "^2.0 || ^3.0"
    }
}

In diesem Fall darf Composer entweder eine passende 2er- oder 3er-Version installieren.

dev-Versionen und Branches

Nicht jede Abhängigkeit muss auf einem offiziellen Release-Tag basieren. Composer kann auch direkt einen Branch einbinden, zum Beispiel dev-main.

{
    "require": {
        "vendor/paket": "dev-main"
    }
}

Das ist praktisch in der Entwicklung oder bei internen Paketen, für produktive Anwendungen aber mit Vorsicht zu genießen. Ein Branch kann sich jederzeit ändern, ohne dass eine saubere Release-Grenze existiert.

Stability-Flags in Composer

Composer kennt verschiedene Stabilitätsstufen: dev, alpha, beta, RC und stable. Mit einem Stability-Flag kannst du Ausnahmen gezielt erlauben.

{
    "require": {
        "vendor/paket": "^2.0@beta"
    }
}

Damit dürfen innerhalb dieses Bereichs auch Beta-Versionen verwendet werden. Das ist nützlich, wenn du ein neues Release testen willst, ohne dein ganzes Projekt auf instabile Pakete umzustellen.

Häufig tauchen außerdem diese beiden Einstellungen auf:

{
    "minimum-stability": "stable",
    "prefer-stable": true
}

Diese Kombination ist in vielen Projekten sinnvoll, weil sie grundsätzlich stabile Releases bevorzugt, einzelne Ausnahmen aber trotzdem zulässt.

Was man in der Praxis beachten sollte

Genau hier passieren in echten Projekten die meisten Fehler. Nicht wegen der Syntax selbst, sondern weil ihre Wirkung falsch eingeschätzt wird.

  • Verwende ^, wenn du normale kompatible Updates zulassen willst.
  • Setze exakte Versionen nur dann ein, wenn du wirklich hart pinnen musst.
  • Nutze dev-main nicht leichtfertig in produktiven Anwendungen.
  • Halte Versionsregeln in der composer.json und die tatsächlichen Stände in der composer.lock auseinander.
  • Prüfe nach Änderungen immer, welche Updates Composer tatsächlich durchführen würde.
  • Zu offene Regeln machen Wartung nicht einfacher, sondern oft unberechenbarer.

Hilfreiche Composer-Befehle

Wer Versionskonflikte oder Update-Spielräume besser verstehen will, sollte diese Befehle kennen:

composer validate
composer show
composer outdated
composer update vendor/paket

Gerade composer outdated ist im Alltag nützlich, weil du schnell siehst, ob ein Paket veraltet ist oder ob deine aktuelle Versionsangabe ein Update verhindert.

Best Practice: Wenn du keine besondere Ausnahme brauchst, starte mit ^. Das ist in den meisten Composer-Projekten die sauberste Balance aus Stabilität, Wartbarkeit und Updatefähigkeit.

Fazit

Die Versionsangaben in der composer.json sind kein Nebendetail, sondern ein zentraler Teil jeder sauberen PHP-Wartung. Wer versteht, wie ^, ~, Wildcards, Bereiche und Stability-Flags funktionieren, vermeidet viele typische Composer-Probleme schon im Vorfeld.

Am Ende geht es nicht darum, möglichst komplizierte Regeln zu bauen, sondern die richtige Balance zu finden: genug Freiraum für sichere Updates, aber genug Kontrolle, damit das Projekt berechenbar bleibt.