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

Php Semver Laravel Package

vierbergenlars/php-semver

A PHP implementation of Semantic Versioning: parse, validate, compare, and sort SemVer version strings, and check them against constraints like ^1.2, ~2.0, or ranges. Lightweight, dependency-free, and ideal for package managers, release tooling, and update checks in any PHP project.

View on GitHub
Deep Wiki
Context7

Getting Started

Install with Composer — the package is a plain library with no Laravel service provider, facade, config file, or migrations:

composer require vierbergenlars/php-semver

Everything autoloads under the vierbergenlars\Semver namespace. The three entry points you will use 95% of the time are:

  • Semver\Semver — static helper: satisfies(), satisfiedBy(), sort(), rsort(), maxSatisfying(), validVersion(), validRange()
  • Semver\Version — parsed version object: parse(), getMajor(), getMinor(), getPatch(), getPreRelease(), getBuild(), getVersionString(), incMajor()/incMinor()/incPatch()
  • Semver\Comparator — pairwise comparison: compare(), greaterThan(), lessThan(), equals(), etc.

First practical use case: gate a feature or endpoint on a minimum application/client version.

use vierbergenlars\Semver\Semver;
use vierbergenlars\Semver\Comparator;

Semver::satisfies('2.4.1', '^2.0');            // true
Comparator::greaterThanOrEqualTo('2.4.1', '2.3.0'); // true
Semver::validVersion('2.4.1-rc.1');             // true

That is enough to ship a middleware or validation rule in a single sitting — no bootstrapping required.

Implementation Patterns

Range gating from config. Keep the constraint in config/ so ops can change a cutoff without a deploy, and resolve the current version once in the container:

// AppServiceProvider::register()
$this->app->singleton(\App\Support\VersionGate::class, fn () => new \App\Support\VersionGate(
    config('app.version', '0.0.0'),
));

// App\Support\VersionGate
final class VersionGate
{
    public function __construct(private readonly string $current) {}

    public function allows(string $range): bool
    {
        return Semver::validRange($range) && Semver::satisfies($this->current, $range);
    }
}

HTTP middleware for client version headers. Mobile apps and SDKs typically send X-App-Version; compare it against a minimum before hitting controllers:

public function handle(Request $request, Closure $next): Response
{
    $client = (string) $request->header('X-App-Version');
    $min    = (string) config('app.min_client_version');

    if (! Semver::validVersion($client) || Comparator::lessThan($client, $min)) {
        return response()->json(['error' => 'upgrade_required', 'min' => $min], 426);
    }

    return $next($request);
}

Note the two-step check: always validate with validVersion() before comparing, because Comparator and satisfies() assume parseable input.

A Laravel validation rule for stored version fields. Plugin manifests, package records, and release tables all benefit from rejecting junk at the boundary:

final class SemanticVersion implements ValidationRule
{
    public function __construct(private readonly bool $range = false) {}

    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        $ok = $this->range
            ? Semver::validRange((string) $value)
            : Semver::validVersion((string) $value);

        if (! $ok) {
            $fail("The {$attribute} field must be a valid semantic ".($this->range ? 'range.' : 'version.'));
        }
    }
}

Picking a compatible plugin/driver in an add-on system. This is where satisfiedBy() and maxSatisfying() earn their keep:

$candidates = $plugins->pluck('version')->all();

$compatible = Semver::satisfiedBy($candidates, '^3.1');   // all that fit
$best       = Semver::maxSatisfying($candidates, '^3.1'); // highest that fits

$ordered = Semver::rsort($candidates); // newest-first for a changelog UI
$sorted  = Semver::sort($candidates);  // oldest-first for upgrade paths

Sanitize the input list first (array_filter($candidates, [Semver::class, 'validVersion'])) — one malformed string can abort the whole operation.

Version bumping in admin tooling. Instead of string surgery on "1.4.2":

$next = Version::parse($release->version)->incMinor(); // Version object, 1.5.0
$release->update(['version' => $next->getVersionString()]);

incMajor/incMinor/incPatch return new immutable instances, so it composes cleanly.

Blade/UI feature flags.

@if (app(VersionGate::class)->allows('>=2.3 <3.0'))
    <x-new-dashboard />
@endif

Caching hot comparisons. Range checks are cheap but not free, and header middleware runs on every request. Memoize the small set of outcomes you actually care about:

$allowed = Cache::remember(
    "gate:{$client}:{$min}",
    now()->addHour(),
    fn () => Comparator::greaterThanOrEqualTo($client, $min),
);

Gotchas and Tips

  • The package is archived. Last release was May 2023 and there will be no further patches. For new code — especially anything parsing untrusted input or resolving Composer constraints — strongly consider composer/semver, which is actively maintained and is what Composer itself uses. Keep this package where it already works, but do not make it a foundational dependency.
  • License is reported as NOASSERTION. GitHub could not detect a license, so verify LICENSE/composer.json yourself before shipping in a commercial product. Do not assume MIT.
  • Pre-release versions do not satisfy ordinary ranges. Semver::satisfies('2.0.0-rc.1', '^2.0.0') is false, matching node-semver semantics. If you want RCs to pass, the range itself must mention a pre-release (e.g. ^2.0.0-rc.1) or you must special-case it. This is the single most common source of "why did my beta build get rejected" tickets.
  • Build metadata is ignored in ordering. 1.0.0+build.5 and 1.0.0+build.9 compare equal; getBuild() is informational only. Do not encode ordering there.
  • Full x.y.z is required for Version::parse(). "1.2" and "1" typically fail validation — normalize/coerce before parsing if your data is sloppy. Likewise, a leading v (v1.2.3) is not handled loosely; strip it with ltrim($value, 'vV') at the boundary.
  • Always gate with validVersion() / validRange() before comparing. Comparison on unparsed junk throws rather than returning false, so a try/catch around user-supplied strings is mandatory in middleware and form requests. valid* methods are the safe predicate form.
  • Wrap parse-heavy loops. If you are sorting or filtering a large collection, validate once up front and reuse the cleaned array. Semver::sort() on a mixed list is a fast way to a 500.
  • Namespace is vierbergenlars\Semver, not Semver. PSR-4 case matters on Linux production images even when it "works" on macOS. Import the fully qualified class names or you will chase ghost autoload errors.
  • No extension points to speak of. Version is a concrete class without an interface; if you need testability, wrap it behind your own VersionGate-style contract rather than mocking Semver statics. That also lets you swap in composer/semver later without touching call sites.
  • Debugging recipe: when a gate misbehaves, log $raw, Semver::validVersion($raw), Version::parse($raw)->getVersionString(), and the range string together. Most surprises are (a) an empty/trimmed header, (b) a pre-release, or (c) a v prefix — in that order.
  • Check the PHP constraint in composer.json before upgrading your runtime; an archived package will not gain compatibility with newer PHP minors. Pin it and test the upgrade explicitly.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings