z4kn4fein/php-semver

PHP语义化版本库。它实现了完整的语义版本2.0.0规范,并提供了解析、比较和递增语义版本以及验证约束的能力。

v3.0.0 2024-04-01 16:17 UTC

README

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

PHP语义化版本库。它实现了完整的语义版本2.0.0规范,并提供了解析、比较和递增语义版本以及验证约束的能力。

需求

使用Composer安装

composer require z4kn4fein/php-semver

使用方法

以下选项可用于构建Version

  1. 使用Version::create()逐步构建。

    Version::create(3, 5, 2, "alpha", "build");
  2. 使用Version::parse()Version::parseOrNull()从字符串解析。

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

构建的Version对象上可访问以下信息

<?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

严格与宽松解析

默认情况下,版本解析器将部分版本(如1.0)和以v前缀开始的版本视为无效。可以通过将strict参数设置为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

比较

可以使用以下比较方法比较两个Version对象。

<?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

排序

Version::sort()Version::sortString()可用于排序版本数组。

<?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"

如果您想按反向顺序排序,则可以使用Version::rsort()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()Version::compareString()方法也可以用作usort()的回调来排序版本数组。

<?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"

约束

使用约束,可以验证版本是否满足一组规则。约束可以描述为一组条件,这些条件通过逻辑ORAND运算符组合。

条件

条件通常由比较运算符和版本组成,如>=1.2.0。条件>=1.2.0将由任何大于或等于1.2.0的版本满足。

支持的比较运算符

  • = 相等(相当于无运算符:1.2.0意味着=1.2.0
  • != 不相等
  • < 小于
  • <= 小于等于
  • > 大于
  • >= 大于等于

可以使用空格将条件连接起来,表示它们之间的逻辑AND运算符。OR运算符可以用|||在条件集中表示。

例如,约束>=1.2.0 <3.0.0 || >4.0.0表示:仅允许那些大于或等于1.2.0且小于3.0.0或大于4.0.0的版本。

我们可以注意到前一个约束的第一个部分(>=1.2.0 <3.0.0)是一个简单的语义版本范围。还有更多表达版本范围的方式;下一节将介绍所有可用的选项。

范围条件

有一些特定的范围指示符,它们是更广泛的范围表达式的简写。

  • X-Range:可以使用xX*字符作为版本数字部分的通配符。

    • 1.2.x 转换为 >=1.2.0 <1.3.0-0
    • 1.x 转换为 >=1.0.0 <2.0.0-0
    • * 转换为 >=0.0.0

    在部分版本表达式中,缺失的数字被视为通配符。

    • 1.2 表示 1.2.x,最终转换为 >=1.2.0 <1.3.0-0
    • 1 表示 1.x1.x.x,最终转换为 >=1.0.0 <2.0.0-0
  • 连字符范围:描述一个包含的版本范围。通配符将被评估并在最终范围内考虑。

    • 1.0.0 - 1.2.0 转换为 >=1.0.0 <=1.2.0
    • 1.1 - 1.4.0 表示 >=(>=1.1.0 <1.2.0-0) <=1.4.0,最终转换为 >=1.1.0 <=1.4.0
    • 1.1.0 - 2 表示 >=1.1.0 <=(>=2.0.0 <3.0.0-0),最终转换为 >=1.1.0 <3.0.0-0
  • 波浪号范围 (~):当指定次要版本时,描述补丁级别范围;未指定时,描述次要级别范围。

    • ~1.0.1 转换为 >=1.0.1 <1.1.0-0
    • ~1.0 转换为 >=1.0.0 <1.1.0-0
    • ~1 转换为 >=1.0.0 <2.0.0-0
    • ~1.0.0-alpha.1 转换为 >=1.0.1-alpha.1 <1.1.0-0
  • 插入符号范围 (^):描述与版本最左非零部分的有关范围。

    • ^1.1.2 转换为 >=1.1.2 <2.0.0-0
    • ^0.1.2 转换为 >=0.1.2 <0.2.0-0
    • ^0.0.2 转换为 >=0.0.2 <0.0.3-0
    • ^1.2 转换为 >=1.2.0 <2.0.0-0
    • ^1 转换为 >=1.0.0 <2.0.0-0
    • ^0.1.2-alpha.1 转换为 >=0.1.2-alpha.1 <0.2.0-0

验证

让我们看看我们如何确定一个版本是否满足约束。

<?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

增加

Version 对象可以使用 getNext{Major|Minor|Patch|PreRelease}Version 方法生成自己的增加版本。这些方法可以用来确定下一个版本,按相应部分顺序增加。Version 对象是 不可变的,所以每个增加函数都会创建一个新的 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

在不稳定版本的情况下

<?php

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

$unstableVersion = Version::parce("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

每个增加函数都提供了在增加版本上设置预发布标识符的选项。

<?php

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

$version = Version::parce("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() 方法创建特定版本的副本。它允许使用可选参数更改复制的版本属性。

$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

注意

如果不设置任何可选参数,则 copy() 方法将生成原始版本的精确副本。

无效版本处理

当版本或约束解析因格式无效而失败时,库抛出特定的 SemverException

注意

可以使用 Version::parseOrNull()Constraint::parseOrNull() 方法进行异常无转换,因为当解析失败时,它们返回 null

联系 & 支持

  • 为错误报告和功能请求创建一个 问题
  • 为你的问题和想法启动一个 讨论
  • 添加 ⭐️ 以支持项目!