composer require z4kn4fein/php-semver
use z4kn4fein\SemVer\Version;
$version = Version::parse('1.2.3-alpha');
$constraint = Version::parseConstraint('>=1.2.0');
if ($version->isSatisfying($constraint)) {
// Proceed with logic for compatible versions
}
z4kn4fein\SemVer\Version (parsing, comparison, incrementing).z4kn4fein\SemVer\Constraints\Constraint (validation logic).z4kn4fein\SemVer\Inc (constants for MAJOR, MINOR, etc.).Version Parsing and Comparison Parse versions from user input (e.g., API requests, config files) and compare them:
$userVersion = Version::parse(request('version'));
if ($userVersion->isGreaterThan(Version::parse('2.0.0'))) {
// Enable new features
}
Dependency Validation
Validate package versions against constraints (e.g., in a composer.json parser):
$constraint = Version::parseConstraint('^1.2.0');
$installedVersion = Version::parse('1.2.3');
if (!$installedVersion->isSatisfying($constraint)) {
throw new \RuntimeException('Version mismatch');
}
Version Sorting Sort version arrays (e.g., for changelog generation):
$versions = Version::sortString([
'1.0.0-alpha',
'1.0.1',
'1.0.0-beta',
]);
Automated Version Bumping Increment versions in CI/CD pipelines or release scripts:
$currentVersion = Version::parse('1.2.3');
$nextVersion = $currentVersion->inc(\z4kn4fein\SemVer\Inc::PATCH);
file_put_contents('VERSION', (string)$nextVersion);
VersionManager facade to centralize version logic:
// app/Providers/AppServiceProvider.php
public function register()
{
$this->app->singleton('version', function () {
return new VersionManager();
});
}
// app/Services/VersionManager.php
class VersionManager {
public function parse(string $version): Version {
return Version::parse($version);
}
}
use Illuminate\Validation\Rule;
$validator = Validator::make($request->all(), [
'version' => ['required', function ($attribute, $value, $fail) {
$constraint = Version::parseConstraint('~1.0.0');
if (!Version::satisfies($value, $constraint)) {
$fail('Version must be ~1.0.0');
}
}],
]);
php artisan version:bump):
// app/Console/Commands/BumpVersion.php
class BumpVersion extends Command {
protected $signature = 'version:bump {type=minor}';
public function handle() {
$version = Version::parse(file_get_contents('VERSION'));
$newVersion = $version->inc(match ($this->argument('type')) {
'major' => Inc::MAJOR,
'minor' => Inc::MINOR,
default => Inc::PATCH,
});
file_put_contents('VERSION', (string)$newVersion);
$this->info("Bumped version to {$newVersion}");
}
}
Strict Parsing Defaults
Version::parse() rejects partial versions (e.g., 1.2) and v-prefixed versions (e.g., v2.3.0).Version::parse($version, false) for loose parsing or handle exceptions with Version::parseOrNull().Immutable Objects
Version methods return new instances; original objects are unchanged.$newVersion = $version->inc(Inc::PATCH)->copy(null, null, null, 'beta');
Pre-Release Handling
1.0.0-alpha) may reset numeric parts:
$version = Version::parse('1.0.0-alpha.1');
$nextPatch = $version->getNextPatchVersion(); // 1.0.0 (not 1.0.1-alpha.2)
getNextPreReleaseVersion() to increment pre-release identifiers.Constraint Parsing Quirks
*, x) and ranges (1.0.0 - 2.0.0) are parsed strictly. Invalid ranges (e.g., 2.0.0 - 1.0.0) throw exceptions.try {
$constraint = Version::parseConstraint('>=1.0.0 <2.0.0');
} catch (\z4kn4fein\SemVer\SemverException $e) {
// Handle invalid constraint
}
Build Metadata Ignored in Comparisons
+build.123) is stripped before comparisons:
Version::equal('1.0.0+build.1', '1.0.0'); // true
withoutSuffixes() to normalize versions for comparison.$version = Version::parse('1.2.3-alpha');
\Log::debug('Parsed version:', ['version' => (string)$version, 'major' => $version->getMajor()]);
$constraint = Version::parseConstraint('~1.2.0 || >=2.0.0');
\Log::debug('Constraint parts:', [
'left' => $constraint->getLeft(),
'right' => $constraint->getRight(),
'operator' => $constraint->getOperator(),
]);
$testVersions = ['1.0', 'v2.0.0', '1.0.0-alpha-0', '1.0.0+exp.sha.5114f85'];
foreach ($testVersions as $version) {
try {
$parsed = Version::parse($version, false);
\Log::info("Parsed: {$version} => {$parsed}");
} catch (\Exception $e) {
\Log::error("Failed to parse {$version}: {$e->getMessage()}");
}
}
Custom Constraints
Extend z4kn4fein\SemVer\Constraints\Constraint to support domain-specific rules:
class CustomConstraint extends Constraint {
public static function parse(string $constraint): self {
// Implement custom parsing logic
}
public function isSatisfiedBy(Version $version): bool {
// Custom validation logic
}
}
Version Storage
Create a VersionRepository to persist versions (e.g., in a database):
class VersionRepository {
public function find(string $version): ?Version {
$record = Model::where('version', $version)->first();
return $record ? Version::parse($record->version) : null;
}
}
Laravel Package Integration Publish config for version-related settings (e.g., default constraints):
// config/version.php
return [
'default_constraint' => '~1.0.0',
'strict_parsing' => env('VERSION_STRICT_PARSING', true),
];
Load in config/app.php under providers.
Event Listeners Trigger events on version changes (e.g., for notifications):
// app/Providers/EventServiceProvider.php
protected $listen = [
\z4kn4fein\SemVer\Events\VersionBumped
How can I help you explore Laravel packages today?