z4kn4fein/php-semver 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

z4kn4fein/php-semver

Composer 安装命令:

composer require z4kn4fein/php-semver

包简介

Semantic Versioning library for PHP. It implements the full semantic version 2.0.0 specification and provides ability to parse, compare, and increment semantic versions along with validation against constraints.

README 文档

README

Build Status Latest Stable Version Total Downloads Sonar Quality Gate Sonar Coverage

Semantic Versioning library for PHP. It implements the full semantic version 2.0.0 specification and provides ability to parse, compare, and increment semantic versions along with validation against constraints.

Requirements

Version PHP Version
>=1.0, <1.2 >=5.5
>=1.2, <3.0 >=7.1
>=3.0 >=8.1

Install with Composer

composer require z4kn4fein/php-semver

Usage

The following options are supported to construct a Version:

  1. Building part by part with Version::create().

    Version::create(3, 5, 2, "alpha", "build");
  2. Parsing from a string with Version::parse() or Version::parseOrNull().

    Version::parse("3.5.2-alpha+build");

The following information is accessible on a constructed Version object:

<?php

use z4kn4fein\SemVer\Version;

$version = Version::parse("2.5.6-alpha.12+build.34");

echo $version->getMajor();         // 2
echo $version->getMinor();         // 5
echo $version->getPatch();         // 6
echo $version->getPreRelease();    // alpha.12
echo $version->getBuildMeta();     // build.34
echo $version->isPreRelease();     // true
echo $version->isStable();         // false
echo $version->withoutSuffixes();  // 2.5.6
echo $version;                     // 2.5.6-alpha.12+build.34

Strict vs. Loose Parsing

By default, the version parser considers partial versions like 1.0 and versions starting with the v prefix invalid. This behaviour can be turned off by setting the strict parameter to false.

echo Version::parse("v2.3-alpha");             // exception
echo Version::parse("2.1");                    // exception
echo Version::parse("v3");                     // exception

echo Version::parse("v2.3-alpha", false);      // 2.3.0-alpha
echo Version::parse("2.1", false);             // 2.1.0
echo Version::parse("v3", false);              // 3.0.0

Compare

It is possible to compare two Version objects with the following comparison methods.

<?php

use z4kn4fein\SemVer\Version;

// with static methods
echo Version::lessThan("2.3.4", "2.4.1");                            // true
echo Version::lessThanOrEqual("2.4.1", "2.4.1");                     // true
echo Version::greaterThan("2.3.1-alpha.5", "2.3.1-alpha.3");         // true
echo Version::greaterThanOrEqual("3.2.3","3.2.2");                   // true
echo Version::equal("3.2.3","3.2.3+build.3");                        // true
echo Version::notEqual("3.2.3","2.2.4");                             // true

// compare() or compareString()
echo Version::compare(Version::parse("2.3.4"), Version::parse("2.4.1"));  // -1
echo Version::compare(Version::parse("2.3.4"), Version::parse("2.3.4"));  // 0
echo Version::compare(Version::parse("2.3.4"), Version::parse("2.2.0"));  // 1

echo Version::compareString("2.3.4", "2.4.1");                            // -1
echo Version::compareString("2.3.4", "2.3.4");                            // 0
echo Version::compareString("2.3.4", "2.2.0");                            // 1


// with instance methods
$version = Version::parse("2.5.6-alpha.12+build.34");

echo $version->isLessThan(Version::parse("2.3.1"));                  // false
echo $version->isLessThanOrEqual(Version::parse("2.5.6-alpha.15"));  // true
echo $version->isGreaterThan(Version::parse("2.5.6"));               // false
echo $version->isLessThanOrEqual(Version::parse("2.5.6-alpha.12"));  // true
echo $version->isEqual(Version::parse("2.5.6-alpha.12+build.56"));   // true
echo $version->isNotEqual(Version::parse("2.2.4"));                  // true

Sort

Version::sort() and Version::sortString() are available to sort an array of versions.

<?php

use z4kn4fein\SemVer\Version;

$versions = array_map(function(string $version) {
    return Version::parse($version);
}, [
    "1.0.1",
    "1.0.1-alpha",
    "1.0.1-alpha.beta",
    "1.0.1-alpha.3",
    "1.0.1-alpha.2",
    "1.1.0",
    "1.1.0+build",
]);

$sorted = Version::sort($versions);

// The result:
//   "1.0.1-alpha"
//   "1.0.1-alpha.2"
//   "1.0.1-alpha.3"
//   "1.0.1-alpha.beta"
//   "1.0.1"
//   "1.1.0"
//   "1.1.0+build"

You might want to sort in reverse order, then you can use Version::rsort() or Version::rsortString().

<?php

use z4kn4fein\SemVer\Version;

$versions = array_map(function(string $version) {
    return Version::parse($version);
}, [
    "1.0.1",
    "1.0.1-alpha",
    "1.0.1-alpha.beta",
    "1.0.1-alpha.3",
    "1.0.1-alpha.2",
    "1.1.0",
    "1.1.0+build",
]);

$sorted = Version::rsort($versions);

// The result:
//   "1.1.0"
//   "1.1.0+build"
//   "1.0.1"
//   "1.0.1-alpha.beta"
//   "1.0.1-alpha.3"
//   "1.0.1-alpha.2"
//   "1.0.1-alpha"

Version::compare() and Version::compareString() methods also can be used as callback for usort() to sort an array of versions.

<?php

use z4kn4fein\SemVer\Version;

$versions = array_map(function(string $version) {
    return Version::parse($version);
}, [
    "1.0.1",
    "1.0.1-alpha",
    "1.0.1-alpha.beta",
    "1.0.1-alpha.3",
    "1.0.1-alpha.2",
    "1.1.0",
    "1.1.0+build",
]);

usort($versions, ["z4kn4fein\SemVer\Version", "compare"]);

// The result:
//   "1.0.1-alpha"
//   "1.0.1-alpha.2"
//   "1.0.1-alpha.3"
//   "1.0.1-alpha.beta"
//   "1.0.1"
//   "1.1.0"
//   "1.1.0+build"

Constraints

With constraints, it's possible to validate whether a version satisfies a set of rules or not. A constraint can be described as one or more conditions combined with logical OR and AND operators.

Conditions

Conditions are usually composed of a comparison operator and a version like >=1.2.0. The condition >=1.2.0 would be met by any version that greater than or equal to 1.2.0.

Supported comparison operators:

  • = Equal (equivalent to no operator: 1.2.0 means =1.2.0)
  • != Not equal
  • < Less than
  • <= Less than or equal
  • > Greater than
  • >= Greater than or equal

Conditions can be joined together with whitespace, representing the AND logical operator between them. The OR operator can be expressed with || or | between condition sets.

For example, the constraint >=1.2.0 <3.0.0 || >4.0.0 translates to: Only those versions are allowed that are either greater than or equal to 1.2.0 {AND} less than 3.0.0 {OR} greater than 4.0.0.

We can notice that the first part of the previous constraint (>=1.2.0 <3.0.0) is a simple semantic version range. There are more ways to express version ranges; the following section will go through all the available options.

Range Conditions

There are particular range indicators which are sugars for more extended range expressions.

  • X-Range: The x, X, and * characters can be used as a wildcard for the numeric parts of a version.

    • 1.2.x translates to >=1.2.0 <1.3.0-0
    • 1.x translates to >=1.0.0 <2.0.0-0
    • * translates to >=0.0.0

    In partial version expressions, the missing numbers are treated as wildcards.

    • 1.2 means 1.2.x which finally translates to >=1.2.0 <1.3.0-0
    • 1 means 1.x or 1.x.x which finally translates to >=1.0.0 <2.0.0-0
  • Hyphen Range: Describes an inclusive version range. Wildcards are evaluated and taken into account in the final range.

    • 1.0.0 - 1.2.0 translates to >=1.0.0 <=1.2.0
    • 1.1 - 1.4.0 means >=(>=1.1.0 <1.2.0-0) <=1.4.0 which finally translates to >=1.1.0 <=1.4.0
    • 1.1.0 - 2 means >=1.1.0 <=(>=2.0.0 <3.0.0-0) which finally translates to >=1.1.0 <3.0.0-0
  • Tilde Range (~): Describes a patch level range when the minor version is specified or a minor level range when it's not.

    • ~1.0.1 translates to >=1.0.1 <1.1.0-0
    • ~1.0 translates to >=1.0.0 <1.1.0-0
    • ~1 translates to >=1.0.0 <2.0.0-0
    • ~1.0.0-alpha.1 translates to >=1.0.1-alpha.1 <1.1.0-0
  • Caret Range (^): Describes a range with regard to the most left non-zero part of the version.

    • ^1.1.2 translates to >=1.1.2 <2.0.0-0
    • ^0.1.2 translates to >=0.1.2 <0.2.0-0
    • ^0.0.2 translates to >=0.0.2 <0.0.3-0
    • ^1.2 translates to >=1.2.0 <2.0.0-0
    • ^1 translates to >=1.0.0 <2.0.0-0
    • ^0.1.2-alpha.1 translates to >=0.1.2-alpha.1 <0.2.0-0

Validation

Let's see how we can determine whether a version satisfies a constraint or not.

<?php

use z4kn4fein\SemVer\Version;
use z4kn4fein\SemVer\Constraints\Constraint;

$constraint = Constraint::parse(">=1.2.0");
$version = Version::parse("1.2.1");

echo $version->isSatisfying($constraint);     // true
echo $constraint->isSatisfiedBy($version);    // true

// Or using the static satisfies() method with strings:
echo Version::satisfies("1.2.1", ">=1.2.0");  // true

Increment

Version objects can produce incremented versions of themselves with the getNext{Major|Minor|Patch|PreRelease}Version methods. These methods can be used to determine the next version in order incremented by the according part. Version objects are immutable, so each incrementing function creates a new Version.

This example shows how the incrementation works on a stable version:

<?php

use z4kn4fein\SemVer\Version;
use z4kn4fein\SemVer\Inc;

$stableVersion = Version::create(1, 0, 0);

echo $stableVersion->getNextMajorVersion();        // 2.0.0
echo $stableVersion->getNextMinorVersion();        // 1.1.0
echo $stableVersion->getNextPatchVersion();        // 1.0.1
echo $stableVersion->getNextPreReleaseVersion();   // 1.0.1-0

// or with the inc() method:
echo $stableVersion->inc(Inc::MAJOR);              // 2.0.0
echo $stableVersion->inc(Inc::MINOR);              // 1.1.0
echo $stableVersion->inc(Inc::PATCH);              // 1.0.1
echo $stableVersion->inc(Inc::PRE_RELEASE);        // 1.0.1-0

In case of an unstable version:

<?php

use z4kn4fein\SemVer\Version;
use z4kn4fein\SemVer\Inc;

$unstableVersion = Version::parse("1.0.0-alpha.2+build.1");

echo $unstableVersion->getNextMajorVersion();        // 2.0.0
echo $unstableVersion->getNextMinorVersion();        // 1.1.0
echo $unstableVersion->getNextPatchVersion();        // 1.0.0
echo $unstableVersion->getNextPreReleaseVersion();   // 1.0.0-alpha.3

// or with the inc() method:
echo $unstableVersion->inc(Inc::MAJOR);              // 2.0.0
echo $unstableVersion->inc(Inc::MINOR);              // 1.1.0
echo $unstableVersion->inc(Inc::PATCH);              // 1.0.0
echo $unstableVersion->inc(Inc::PRE_RELEASE);        // 1.0.0-alpha.3

Each incrementing function provides the option to set a pre-release identity on the incremented version.

<?php

use z4kn4fein\SemVer\Version;
use z4kn4fein\SemVer\Inc;

$version = Version::parse("1.0.0-alpha.1");

echo $version->getNextMajorVersion("beta");         // 2.0.0-beta
echo $version->getNextMinorVersion("");             // 1.1.0-0
echo $version->getNextPatchVersion("alpha");        // 1.0.1-alpha
echo $version->getNextPreReleaseVersion("alpha");   // 1.0.0-alpha.2

// or with the inc() method:
echo $version->inc(Inc::MAJOR, "beta");             // 2.0.0-beta
echo $version->inc(Inc::MINOR, "");                 // 1.1.0-0
echo $version->inc(Inc::PATCH, "alpha");            // 1.0.1-alpha
echo $version->inc(Inc::PRE_RELEASE, "alpha");      // 1.0.0-alpha.2

Copy

It's possible to make a copy of a particular version with the copy() method. It allows altering the copied version's properties with optional parameters.

$version = Version::parse("1.0.0-alpha.2+build.1");

echo $version->copy();                                        // 1.0.0-alpha.2+build.1
echo $version->copy(3);                                       // 3.0.0-alpha.2+build.1
echo $version->copy(null, 4);                                 // 1.4.0-alpha.2+build.1
echo $version->copy(null, null, 5);                           // 1.0.5-alpha.2+build.1
echo $version->copy(null, null, null, "alpha.4");             // 1.0.0-alpha.4+build.1
echo $version->copy(null, null, null, null, "build.3");       // 1.0.0-alpha.2+build.3
echo $version->copy(3, 4, 5);                                 // 3.4.5-alpha.2+build.1

Note

Without setting any optional parameter, the copy() method will produce an exact copy of the original version.

Invalid version handling

When the version or constraint parsing fails due to an invalid format, the library throws a specific SemverException.

Note

The Version::parseOrNull() and Constraint::parseOrNull() methods can be used for exception-less conversions as they return null when the parsing fails.

Contact & Support

  • Create an issue for bug reports and feature requests.
  • Start a discussion for your questions and ideas.
  • Add a ⭐️ to support the project!

z4kn4fein/php-semver 适用场景与选型建议

z4kn4fein/php-semver 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 1.64M 次下载、GitHub Stars 达 25, 最近一次更新时间为 2019 年 12 月 25 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「version」 「validation」 「semver」 「versioning」 「semantic」 「comparison」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 z4kn4fein/php-semver 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 z4kn4fein/php-semver 我们能提供哪些服务?
定制开发 / 二次开发

基于 z4kn4fein/php-semver 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 1.64M
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 26
  • 点击次数: 18
  • 依赖项目数: 19
  • 推荐数: 0

GitHub 信息

  • Stars: 25
  • Watchers: 1
  • Forks: 5
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2019-12-25