herrera-io/version
PHP library for Semantic Versioning (SemVer 2.0.0): parse versions into a builder, increment major/minor/patch, edit pre-release/build metadata, validate formats, compare versions, and dump back to strings for release tooling.
Install the Package:
composer require herrera-io/version:^1.1
Note: Use ^1.1 to avoid potential PHP 8.x compatibility issues.
First Use Case: Parsing and Validating Versions
use Herrera\Version\Parser;
use Herrera\Version\Validator;
// Parse a version string
$version = Parser::toVersion('1.2.3-alpha+build123');
// Validate a version string
if (Validator::isVersion('2.0.0')) {
// Proceed with version logic
}
Where to Look First:
doc/04-Parsing.md and doc/02-Comparing.md.Version Parsing and Manipulation
// Parse and modify a version
$builder = Parser::toBuilder('1.2.3-beta');
$builder->incrementMajor()->clearPreRelease();
$finalVersion = $builder->getVersion(); // "2.0.0"
Version Comparison in Laravel Logic
use Herrera\Version\Comparator;
// Compare versions in a service
public function shouldUpgrade(string $currentVersion, string $latestVersion): bool
{
return Comparator::isLessThan(
Parser::toVersion($currentVersion),
Parser::toVersion($latestVersion)
);
}
Validation in Requests/Middleware
// Validate version strings in API requests
public function validateVersion(Request $request)
{
$version = $request->input('version');
if (!Validator::isVersion($version)) {
throw new \InvalidArgumentException("Invalid version format: $version");
}
}
Version-Based Feature Flags
// Enable features based on version ranges
$userVersion = Parser::toVersion($user->version);
if (Comparator::isGreaterThanOrEqual($userVersion, Parser::toVersion('1.5.0'))) {
$this->enableNewFeature();
}
Laravel Service Container: Bind the parser/comparator for dependency injection:
$this->app->singleton(Parser::class);
$this->app->singleton(Comparator::class);
Facade for Cleaner Syntax:
Create a Version facade to abstract the library:
// app/Facades/Version.php
namespace App\Facades;
use Herrera\Version\Parser;
use Illuminate\Support\Facades\Facade;
class Version extends Facade
{
protected static function getFacadeAccessor()
{
return Parser::class;
}
}
Usage:
$version = Version::toVersion('1.2.3');
Artisan Commands: Use the library in release scripts:
// app/Console/Commands/ReleaseCommand.php
public function handle()
{
$builder = Parser::toBuilder(config('app.version'));
$builder->incrementPatch();
config(['app.version' => $builder->getVersion()]);
}
Database Versioning: Store version strings in migrations and compare them:
// Check if a schema update is needed
$currentDbVersion = DB::table('schema_versions')->value('version');
$latestVersion = Parser::toVersion('1.2.0');
if (Comparator::isLessThan($currentDbVersion, $latestVersion)) {
// Run migrations
}
PHP Version Compatibility:
#[ReturnTypeWillChange] or return_type declarations in a fork.toComponents():
#[ReturnTypeWillChange]
public function toComponents(string $version): array { ... }
Strict SemVer Enforcement:
1.2 without patch) throw exceptions. Handle gracefully:
try {
$version = Parser::toVersion('1.2'); // Throws InvalidArgumentException
} catch (\InvalidArgumentException $e) {
// Fallback to default version or log error
}
Build Metadata Handling:
+build123) is ignored in comparisons by default. Explicitly clear it if needed:
$builder = Parser::toBuilder('1.2.3+build123');
$builder->clearBuild(); // Compare without build metadata
Pre-Release Comparisons:
1.0.0-alpha) are considered less than release versions (1.0.0). This may not match your use case. Override logic if needed:
if (Comparator::isGreaterThan($preRelease, $release)) {
// Custom logic for pre-releases
}
Performance in Loops:
$cache = [];
$parsedVersion = $cache[$versionString] ?? Parser::toVersion($versionString);
Inspect Version Components:
Use Parser::toComponents() to debug malformed versions:
$components = Parser::toComponents('1.2.3-alpha+build123');
// Returns: ['major' => 1, 'minor' => 2, 'patch' => 3, 'preRelease' => 'alpha', 'build' => 'build123']
Comparator Edge Cases:
1.0.0-alpha < 1.0.0).1.0.0+build1 == 1.0.0).1.2.3 == 1.2.3).Logging Invalid Versions: Log failed validations to identify user input issues:
Validator::isVersion($input) || \Log::warning("Invalid version: $input");
Custom Validation Rules:
Extend Validator to add project-specific rules:
class CustomValidator extends Validator
{
public static function isProjectVersion(string $version): bool
{
$components = Parser::toComponents($version);
return $components['major'] >= 1 && $components['minor'] >= 0;
}
}
Fork and Modernize: Fork the repository to:
Version::config()).VersionService class for Laravel:
class VersionService
{
public function getAppVersion(): string
{
return config('app.version');
}
public function incrementVersion(): void
{
$builder = Parser::toBuilder($this->getAppVersion());
$builder->incrementPatch();
config(['app.version' => $builder->getVersion()]);
}
}
Integration with Laravel Packages: Use the library in package manifests or service providers:
// In a PackageServiceProvider
public function boot()
{
$packageVersion = Parser::toVersion($this->packageVersion);
if (Comparator::isLessThan($packageVersion, Parser::toVersion('2.0.0'))) {
// Deprecation logic
}
}
Default Version Handling:
The library does not provide a "default version." Define one in your config/versioning.php:
return [
'default' => '0.0.1',
];
Build Metadata in Comparisons:
By default, build metadata (e.g., +build123) is ignored in comparisons. To include it, modify the comparator logic or use a custom implementation.
Case Sensitivity:
Pre-release identifiers (e.g., alpha, ALPHA) are case-sensitive in comparisons. Normalize case if needed:
$builder->setPreRelease(strtolower($builder->getPreRelease()));
How can I help you explore Laravel packages today?