PHPackages                             grazulex/php-semver-sieve - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. grazulex/php-semver-sieve

ActiveLibrary

grazulex/php-semver-sieve
=========================

A pure PHP package for checking if a version string is included in one or more version ranges. Supports SemVer 2.0.0 and multiple version dialects (Composer, npm, PyPI, etc.)

v1.1.0(6mo ago)2107—0%MITPHPPHP ^8.2CI failing

Since Sep 4Pushed 6mo ago1 watchersCompare

[ Source](https://github.com/Grazulex/php-semver-sieve)[ Packagist](https://packagist.org/packages/grazulex/php-semver-sieve)[ Fund](https://www.buymeacoffee.com/Grazulex)[ Fund](https://paypal.me/strauven)[ RSS](/packages/grazulex-php-semver-sieve/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (2)Dependencies (6)Versions (3)Used By (0)

PHP SemVer Sieve
================

[](#php-semver-sieve)

 [![PHP SemVer Sieve](https://raw.githubusercontent.com/Grazulex/php-semver-sieve/main/new_logo.png)](https://raw.githubusercontent.com/Grazulex/php-semver-sieve/main/new_logo.png)**Universal semantic version range checking across all major package managers - powerful, fast, and dependency-free PHP package.**

*A comprehensive library for evaluating version constraints from Composer, npm, PyPI, RubyGems, Maven, NuGet, Go modules, and more with a single unified API.*

[![Latest Version](https://camo.githubusercontent.com/f0f29bc506fd0d478bf973e1c13bd3b91788990198a55ac1d550e46a916a5e5a/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6772617a756c65782f7068702d73656d7665722d73696576652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/grazulex/php-semver-sieve) [![Total Downloads](https://camo.githubusercontent.com/6d9bd1d35538a829419db832b0751baf603b1378ca2530ff4300d9380f8534a8/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6772617a756c65782f7068702d73656d7665722d73696576652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/grazulex/php-semver-sieve) [![License](https://camo.githubusercontent.com/55c0218c8f8009f06ad4ddae837ddd05301481fcf0dff8e0ed9dadda8780713e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265)](https://github.com/Grazulex/php-semver-sieve/blob/main/LICENSE.md) [![PHP Version](https://camo.githubusercontent.com/23afe126ac0b759e5f65a1ca255349b59e62a0ad85e9e7b808e7e5bd7e86bd8f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d382e322532422d626c75652e7376673f7374796c653d666c61742d737175617265)](https://php.net/) [![Tests](https://camo.githubusercontent.com/afdf6cbc4eb1b37b2969a6c1fee2009dc08209f55479558a444fe57c00ae5b99/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6772617a756c65782f7068702d73656d7665722d73696576652f74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/grazulex/php-semver-sieve/actions) [![Static Analysis](https://camo.githubusercontent.com/2506baeb255702212e0acd9201252ec938ba610d1fedb2ca1f51515ca365b702/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6772617a756c65782f7068702d73656d7665722d73696576652f7374617469632d616e616c797369732e796d6c3f6272616e63683d6d61696e266c6162656c3d7068707374616e267374796c653d666c61742d737175617265)](https://github.com/grazulex/php-semver-sieve/actions) [![Mutation Testing](https://camo.githubusercontent.com/a2ab79edbc556d7f08c05bcb6c23388a7da9e18872eadfdd0cbdffd58744262b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6772617a756c65782f7068702d73656d7665722d73696576652f6d75746174696f6e2e796d6c3f6272616e63683d6d61696e266c6162656c3d6d75746174696f6e267374796c653d666c61742d737175617265)](https://github.com/grazulex/php-semver-sieve/actions)

🚀 Overview
----------

[](#-overview)

A **powerful, universal PHP package** for checking if version strings match version ranges across **all major package managers**.

> 🎯 **One API to rule them all** - Handle version constraints from Composer, npm, PyPI, RubyGems, Maven, NuGet, Go modules, and more!

✨ Features
----------

[](#-features)

- 🏗️ **Framework-agnostic** - No Laravel or Composer dependencies
- 🚀 **Zero runtime dependencies** - Pure PHP logic with performance focus
- 📏 **SemVer 2.0.0 compatible** - Follows semantic versioning specification
- 🌍 **8 Package Manager Dialects** - Universal support for all major ecosystems:
    - 🐘 **PHP** (Composer) - `^1.0`, `~1.2`, `>=1.0 `)
    - ☕ **Java** (Maven) - SNAPSHOT versions, range notation
    - 🔷 **C#/.NET** (NuGet) - 4-segment versions, interval notation
    - 🐹 **Go** (Go modules) - `v` prefix, pseudo-versions, incompatible versions
    - 🎯 **Generic SemVer** - Standards-compliant base implementation
- 🏛️ **SOLID Architecture** - Clean, extensible, maintainable codebase
- 🧪 **Fully tested** - 42 tests, 126 assertions, mutation testing
- 🔍 **Static analysis** - PHPStan level 6 compliant
- ⚡ **PHP 8.2+** - Modern features (readonly classes, enums, match expressions)

📊 Project Stats
---------------

[](#-project-stats)

- **24 source files** with **3,600+ lines of code**
- **42 passing tests** with **126 assertions**
- **8 complete dialects** covering all major package managers
- **Zero runtime dependencies** for maximum compatibility
- **100% type coverage** with PHPStan

Installation
------------

[](#installation)

```
composer require grazulex/php-semver-sieve
```

🚀 Quick Start
-------------

[](#-quick-start)

```
use Grazulex\SemverSieve\Sieve;
use Grazulex\SemverSieve\Dialects\GenericSemverDialect;

// Create a sieve instance
$sieve = new Sieve(new GenericSemverDialect());

// Simple boolean check
$matches = $sieve->includes('1.2.3', ['>=1.0 =1.9 =1.9 =2.0.0-0 =1.9.0-0 =1.2, 1.2', '>= 1.0']); // → true

// Java/Maven
$maven = new Sieve(new MavenDialect());
$maven->includes('1.2.3', ['[1.0,2.0)', '1.2+']); // → true

// .NET/NuGet
$nuget = new Sieve(new NugetDialect());
$nuget->includes('1.2.3.4', ['[1.0,2.0)', '1.2.*']); // → true

// Go/Go Modules
$gomod = new Sieve(new GoModDialect());
$gomod->includes('v1.2.3', ['v1.2.3', 'v1.2+incompatible']); // → true
```

📚 Dialect-Specific Features
---------------------------

[](#-dialect-specific-features)

### 🐘 Composer Dialect (PHP)

[](#-composer-dialect-php)

```
use Grazulex\SemverSieve\Dialects\ComposerDialect;
$sieve = new Sieve(new ComposerDialect());

// Composer-specific syntax
$sieve->includes('1.2.3', [
    '^1.0',        // Caret: >=1.0.0 =1.2.0 includes('1.2.3', [
    'latest',           // Special tags
    'next',             // Distribution tags
    'workspace:*',      // Workspace protocol
    'workspace:^1.0',   // Workspace with range
    '1.2.x',           // X-ranges
    '1.x.x',           // Multi-segment X-ranges
]);

// Special npm tags supported:
// latest, next, alpha, beta, rc, canary, experimental, dev, nightly
```

### 🐍 PyPI Dialect (Python)

[](#-pypi-dialect-python)

```
use Grazulex\SemverSieve\Dialects\PypiDialect;
$sieve = new Sieve(new PypiDialect());

// PEP 440 compliant syntax
$sieve->includes('1.2.3', [
    '~=1.2',       // Compatible release
    '===1.2.3',    // Arbitrary equality
    '>=1.0, 1.2',      // Pessimistic: >= 1.2, < 1.3
    '~> 1.2.0',    // Pessimistic: >= 1.2.0, < 1.3.0
    '>= 1.0',      // Standard comparison
]);
```

### ☕ Maven Dialect (Java)

[](#-maven-dialect-java)

```
use Grazulex\SemverSieve\Dialects\MavenDialect;
$sieve = new Sieve(new MavenDialect());

// Maven version ranges and qualifiers
$sieve->includes('1.2.3-SNAPSHOT', [
    '[1.0,2.0)',        // Range: >= 1.0, < 2.0
    '[1.0,2.0]',        // Range: >= 1.0,  1.0, < 2.0
    '1.0+',             // Soft requirement: >= 1.0
]);

// Maven qualifiers ordering:
// alpha < beta < milestone < rc < snapshot < release < sp
```

### 🔷 NuGet Dialect (.NET)

[](#-nuget-dialect-net)

```
use Grazulex\SemverSieve\Dialects\NugetDialect;
$sieve = new Sieve(new NugetDialect());

// NuGet 4-segment versions and interval notation
$sieve->includes('1.2.3.4', [
    '[1.0,2.0)',       // Interval notation
    '1.2.*',           // Floating versions
    '1.*',             // Major floating
    '*',               // Any version
]);
```

### 🐹 Go Modules Dialect

[](#-go-modules-dialect)

```
use Grazulex\SemverSieve\Dialects\GoModDialect;
$sieve = new Sieve(new GoModDialect());

// Go module versions (require 'v' prefix)
$sieve->includes('v1.2.3', [
    'v1.2.3',                    // Exact version
    'v2.0.0+incompatible',       // Incompatible version
]);

// Supports pseudo-versions: v0.0.0-20191109021931-daa7c04131f5
```

### 🎯 Generic SemVer Dialect

[](#-generic-semver-dialect)

```
use Grazulex\SemverSieve\Dialects\GenericSemverDialect;
$sieve = new Sieve(new GenericSemverDialect());

// Standards-compliant SemVer 2.0.0
$sieve->includes('1.2.3-alpha.1+build.1', [
    '>=1.0.0',         // Comparison operators
    '^1.2',            // Caret ranges
    '~1.2.3',          // Tilde ranges
    '1.2.3-alpha.1',   // Prerelease versions
]);
```

📋 Complete Syntax Reference
---------------------------

[](#-complete-syntax-reference)

SyntaxExampleDialectsDescription**Exact**`1.2.3`AllExact version match**Comparators**`>=1.0`, ` 1.2`RubyGemsRuby pessimistic constraint**Wildcards**`1.2.*`, `1.x`, `*`MostWildcard matching**X-Ranges**`1.2.x`, `1.x.x`npmnpm-style X-ranges**Hyphen Ranges**`1.2 - 1.4`Generic, ComposerInclusive range**Interval**`[1.0,2.0)`, `(1.0,2.0]`Maven, NuGetMathematical intervals**OR Logic**`^1.0 || ^2.0`MostMultiple range options**AND Logic**`>=1.0 includes('invalid.version.format', ['^1.0']);
} catch (InvalidVersionException $e) {
    echo "Invalid version: " . $e->getMessage();
    // Access error context
    $context = $e->getContext();
    echo "Failed version: " . $context['version'];
} catch (InvalidRangeException $e) {
    echo "Invalid range: " . $e->getMessage();
} catch (ConfigurationException $e) {
    echo "Configuration error: " . $e->getMessage();
} catch (SemverSieveException $e) {
    // Catch-all for any sieve-related errors
    echo "Sieve error: " . $e->getMessage();
}
```

🏗️ SOLID Architecture Deep Dive
-------------------------------

[](#️-solid-architecture-deep-dive)

### Single Responsibility Principle (SRP)

[](#single-responsibility-principle-srp)

Each class has one clear purpose:

- `Sieve` - Main API facade
- `VersionParser` - Parse version strings
- `RangeParser` - Parse range expressions
- `VersionComparator` - Compare versions
- `RangeEvaluator` - Evaluate range matching

### Open/Closed Principle (OCP)

[](#openclosed-principle-ocp)

- ✅ Add new dialects without modifying existing code
- ✅ Extend with new operators via configuration
- ✅ Plugin architecture for custom behaviors

### Liskov Substitution Principle (LSP)

[](#liskov-substitution-principle-lsp)

- ✅ All dialects are interchangeable via `DialectInterface`
- ✅ Consistent behavior across implementations
- ✅ Polymorphic usage guaranteed

### Interface Segregation Principle (ISP)

[](#interface-segregation-principle-isp)

- ✅ Small, focused interfaces
- ✅ Clients depend only on methods they use
- ✅ No forced dependencies on unused functionality

### Dependency Inversion Principle (DIP)

[](#dependency-inversion-principle-dip)

- ✅ Core classes depend on abstractions (interfaces)
- ✅ Dependency injection throughout
- ✅ High-level modules independent of low-level details

📈 Performance &amp; Benchmarks
------------------------------

[](#-performance--benchmarks)

### Optimizations

[](#optimizations)

- **Immutable objects** - Thread-safe, cacheable
- **Lazy evaluation** - Parse only when needed
- **Memory efficient** - Minimal object allocation
- **Type safety** - PHP 8.2+ strict typing

### Typical Performance

[](#typical-performance)

```
// Version parsing: ~0.1ms per version
// Range evaluation: ~0.05ms per constraint
// Memory usage: ~2KB per Sieve instance
```

🧪 Testing &amp; Quality Assurance
---------------------------------

[](#-testing--quality-assurance)

### Test Coverage

[](#test-coverage)

- **42 tests** with **126 assertions**
- **Unit tests** for all components
- **Integration tests** for end-to-end scenarios
- **Property-based testing** for edge cases
- **Mutation testing** with Infection

### Quality Tools

[](#quality-tools)

- **PHPStan Level 6** - Static analysis
- **PHP-CS-Fixer** - PSR-12 code style
- **Rector** - Automated refactoring
- **Pest** - Modern testing framework

```
# Run complete quality suite
composer quality

# Individual commands
composer test          # Run tests
composer stan          # Static analysis
composer cs-fix         # Fix code style
composer infection      # Mutation testing
```

💼 Real-World Use Cases
----------------------

[](#-real-world-use-cases)

### 🔍 Dependency Analysis Tools

[](#-dependency-analysis-tools)

```
// Analyze if package versions satisfy constraints
$composer = new Sieve(new ComposerDialect());
$compatible = $composer->includes('2.1.5', ['^2.0', '!=2.1.3']);

// Multi-ecosystem dependency checker
$ecosystems = [
    'php' => new ComposerDialect(),
    'js' => new NpmDialect(),
    'python' => new PypiDialect(),
    'java' => new MavenDialect(),
];

foreach ($ecosystems as $name => $dialect) {
    $sieve = new Sieve($dialect);
    $results[$name] = $sieve->includes($version, $constraints);
}
```

### 📦 Package Registry &amp; Mirrors

[](#-package-registry--mirrors)

```
// Filter package versions by compatibility
$npm = new Sieve(new NpmDialect());
$compatibleVersions = array_filter($allVersions, function($version) use ($npm) {
    return $npm->includes($version, ['>=14.0.0', '=1.4']);
$result2 = $sieve->match('1.5.0', ['~1.5', '
