nikolaposa/version
SemVer value object for PHP. Create versions from components or strings, access major/minor/patch plus pre-release/build metadata, compare versions (lt/gt/eq), and match against constraints for validation and dependency-style checks.
Start by installing the package via Composer:
composer require nikolaposa/version
The core classes you’ll use daily are Version (for parsing/representing versions) and Constraint (for expressing version constraints like ^1.2 or >=2.0,<3.0).
Your first use case is likely verifying compatibility between two versions or a version against a requirement:
use Nikolaposa\Version\Version;
use Nikolaposa\Version\Constraint;
$v1 = new Version('1.2.3');
$v2 = new Version('1.2.4');
assert($v1->compareTo($v2) < 0); // true: 1.2.3 < 1.2.4
$constraint = new Constraint('^1.2');
assert($v1->satisfies($constraint)); // true
assert(!$v2->satisfies(new Constraint('^1.0.0-beta'))); // false
Look in src/ for the main entry points (Version, Constraint, ConstraintParser) — the API is intentionally small and consistent.
Use Version to parse and compare semver-like strings. It handles unstable suffixes (e.g., -dev, rc1) and ignores leading v:
$v = new Version('v2.0.0-rc1'); // parsed as 2.0.0-rc1
Typical workflow: accept a user-provided constraint (e.g., from config or CLI) and validate current/required versions:
$desiredVersion = new Version($currentVersionString);
$required = Constraint::parse('>=1.5.0, <2.0.0');
if (!$desiredVersion->satisfies($required)) {
throw new RuntimeException('Version incompatible');
}
Embed constraints as strings and parse once at runtime:
$constraints = array_map(
static fn (string $c): Constraint => Constraint::parse($c),
$config['allowed_versions']
);
Integrate into tools like autoloader plugins, plugin managers, or CLI tools that check compatibility before executing actions:
// In a plugin loader
$pluginVersion = new Version($plugin->getVersion());
if (!$pluginVersion->satisfies(Constraint::parse('^2.0'))) {
throw new RuntimeException('Plugin requires version ^2.0');
}
The parser expects X.Y.Z or X.Y.Z-…. Non-standard formats (e.g., 1.2, v1, 1.2.3-beta) may normalize but can fail unexpectedly. Always test edge cases:
new Version('1.2'); // ✅ becomes 1.2.0
new Version('v1.2'); // ✅ becomes 1.2.0
new Version('1'); // ❌ throws `InvalidArgumentException`
Version normalizes internally to X.Y.Z and stable/unstable parts. Be aware that 1.2.3-dev < 1.2.3 (dev is considered earlier), and pre-release versions only compare meaningfully within the same X.Y.Z base.
Constraints use space- or comma-separated clauses:
>=1.0 <=2.0 → equivalent to 1.0.0 ≤ v ≤ 2.0.0^1.2 is not natively supported — use Constraint::parse('>=1.2.0,<2.0.0') instead (unless the package itself supports semantic caret ranges via extension; the base library doesn’t auto-convert ^).Version::compareTo() returns -1, 0, or 1. Use assert-friendly comparisons in unit tests:
$this->assertSame(-1, $v1->compareTo($v2));
The Constraint class uses a private constructor + Constraint::parse(). To add new constraint syntax (e.g., custom operators), extend ConstraintParser and replace it in your DI layer — the library is designed for this.
This is a standalone library — safe to use in Laravel, Symfony, or plain PHP CLI apps. Just avoid side effects: it has no Composer plugin hooks or autoloader tricks.
How can I help you explore Laravel packages today?