Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Semver Laravel Package

composer/semver

A standalone PHP library for parsing, validating, and comparing semantic version numbers and constraints, extracted from Composer. It normalizes versions, handles stability flags and branches, and powers dependency version checks. Requires PHP 5.3.2+.

View on GitHub
Deep Wiki
Context7

Getting Started

Install with composer require composer/semver — the ^3.5 constraint already allows 3.5.1, but if your lock file resolves to 3.5.0 run composer update composer/semver to pick up the 3.5.1 Intervals::isSubsetOf() fix (see Gotchas). The core entry points are VersionParser, Comparator, Semver, Intervals, and CompilingMatcher — all in the Composer\Semver namespace.

The most common first use case is validating and normalizing version strings (e.g. cleaning "1.2" → "1.2.0.0") or parsing constraints like "^1.2 || ~2.0" for downstream matching.

use Composer\Semver\VersionParser;
use Composer\Semver\Semver;

$parser = new VersionParser();

$parser->isValid('1.2');                  // true  (added in 3.5.0)
$normalized = $parser->normalize('1.2');  // '1.2.0.0'
$constraint = $parser->parseConstraints('^1.2 || ~2.0');

Semver::satisfies($normalized, '^1.2 || ~2.0'); // true

Check validity first with VersionParser::isValid() (3.5.0+) — on older versions normalize() throws UnexpectedValueException, so you'd need a try/catch instead. Use Semver::satisfies() for constraint checks and Semver::sort()/rsort() to order arrays of version strings intelligently.

Implementation Patterns

  • Constraint Parsing & Validation Pipeline: Use VersionParser::parseConstraints() to convert user- or config-provided strings (e.g. from composer.json or CLI flags) into ConstraintInterface objects. Guard the input with isValid() (3.5.0+) so malformed strings fail fast with a clean validation error rather than an exception from normalize(). Then optimize hot constraints with Intervals::compactConstraint() — but only on 3.5.0+, see Gotchas.
  • Version Matching: For conditional logic (e.g. plugin compatibility checks), combine Semver::satisfies() and Semver::satisfiedBy() with normalized versions. Use Comparator for low-level binary comparisons (e.g. sorting UI displays).
  • Pre-release / RC Compatibility Checks: Matching against >=1.0-RC1, <2.0-beta2, etc. is now consistent across alpha, beta, and rc suffixes in 3.5.0. If you gate features on RC versions, write tests that assert both the boundary version and its immediate neighbours, and require ^3.5 in composer.json.
  • Intervals for Optimization: When working with complex constraints (e.g. multi-range versions from dependency resolution), use Intervals::get() to decompose constraints into numeric intervals. Combine with Intervals::isSubsetOf() to check coverage (e.g. "does constraint A fully cover B?") — useful for security scanning or update feasibility checks. Note that a constraint matching nothing (e.g. < 0.0.0) is trivially a subset of any constraint; that result is only correct on 3.5.1+, so require ^3.5.1 when your coverage logic can encounter empty ranges.
  • Batch Matching: For repeated constraint matching (e.g. scanning many versions against one constraint), use CompilingMatcher and call CompilingMatcher::clear() after each batch. 3.5.0 removes per-call cache-key string concatenation, so large scans are measurably cheaper — worth re-benchmarking if you previously avoided it.
  • Branch Handling: Normalize branch names like "dev-main" using VersionParser::normalizeBranch(). It handles aliases (e.g. foobar-dev → dev-foobar) and preserves -dev stability markers for downstream logic.

Gotchas and Tips

  • Upgrade for isSubsetOf() correctness on empty ranges: On 3.5.0, Intervals::isSubsetOf() returns false for < 0.0.0, even though that constraint matches nothing and is therefore a subset of every constraint. If you use subset checks to answer "is every version in A also in B?" — typical in patch-coverage or security-scan logic — a 3.5.0 false negative can flip your conclusion. Bump to 3.5.1 (composer update composer/semver) and add a regression test asserting isSubsetOf() behaviour for an unsatisfiable range.
  • Upgrade for compactConstraint() correctness: Prior to 3.5.0, Intervals::compactConstraint() could turn a constraint that matches no dev versions (e.g. > 1.0.0 != 2.0.0 || < 1.9.0) into != 2.0.0, which does match all dev-* versions. If you use compaction in dependency-resolution or security-scan logic, this silently widens your match set. Require ^3.5 or skip compaction on older versions.
  • Upgrade for RC constraint accuracy: Before 3.5.0, >=/< constraints on RC versions (e.g. >=1.0-RC1) picked up an extra -dev suffix that alpha/beta constraints did not, producing inconsistent boundary behaviour. Pin ^3.5 if you compare against RC releases.
  • isValid() availability: VersionParser::isValid() is new in 3.5.0. On older versions, wrap normalize() in a try/catch for UnexpectedValueException, or check with Semver::satisfies() defensively.
  • Stability Normalization: normalizeStability() expects valid stabilities (dev, alpha, beta, rc, stable). Validate user input with parseStability() first; treat unparseable values as invalid rather than assuming they fall back to stable.
  • Default Branch Warnings: In ^ constraints, * no longer matches dev-* versions (since v3.0.0); * matches stable only, so pre-release installs must be explicit (*@dev or an explicit dev-* constraint).
  • Normalize Before Comparing: Raw strings like "1.0" and "1.0.0.0" behave differently under version_compare; always normalize via VersionParser::normalize() before using Comparator or Semver.
  • CompilingMatcher Lifecycle: It memoizes aggressively by design. Call CompilingMatcher::clear() between batches/requests in long-running workers (Octane, queue workers) to avoid stale results and unbounded memory growth.
  • Constraint Interfaces Are Internal: Do not implement ConstraintInterface yourself — it's marked internal as of v3.0. Use MultiConstraint::create() to generate optimized multi-constraints from arrays of strings instead.
  • Date Versions: ~ constraints support date-style versions (e.g. ~201903.0), but they're fuzzy — always test edge cases if relying on them, and avoid mixing with standard semver unless intentional.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
wandesnet/mercadopago-laravel
tsfcorp/email
larafony/core
laravel-enso/currencies
tartan/laravel-online-payment
gam/laravel-sat-catalogs
cloudcreativity/laravel-stripe
abdulelahragih/querybuilder
wedevbr/celcoin-laravel
surazdott/nepali-date
devsquad-cockpit/laravel
coding-socks/laravel-upload-handler
artisanbarista/laravel-shield
shopwwi/laravel-cache
instance-code/repository
flooris/prestashop-models
lab2view/laravel-generator
lenderspender/laravel-wizard
joecampo/laravel-notification-basecamp
square1/laravel-collection-rolling-average