PHP 怎么自动化版本徽章

wen PHP项目 5

本文目录导读:

PHP 怎么自动化版本徽章

  1. 使用 Shields.io 动态徽章
  2. 自定义 PHP 脚本生成徽章
  3. 使用 Git 钩子自动化更新
  4. CI/CD 集成方案
  5. 实时版本检测系统
  6. 集成到 README 自动更新脚本
  7. 现代化解决方案

我来介绍几种在PHP项目中自动化版本徽章的方法:

使用 Shields.io 动态徽章

从 Packagist 获取版本

// 如果你使用 Composer 发布包
// 直接在 README.md 中添加:
[![Latest Stable Version](https://poser.pugx.org/vendor/package/version)](https://packagist.org/packages/vendor/package)
[![Total Downloads](https://poser.pugx.org/vendor/package/downloads)](https://packagist.org/packages/vendor/package)

从 GitHub Releases 获取

[![GitHub release](https://img.shields.io/github/release/username/repo.svg?style=flat-square)](https://github.com/username/repo/releases)

自定义 PHP 脚本生成徽章

基础版本徽章生成器

<?php
class BadgeGenerator
{
    public static function generateSVGBadge($label, $value, $color = '#007ec6')
    {
        $labelWidth = strlen($label) * 7 + 20;
        $valueWidth = strlen($value) * 7 + 20;
        $totalWidth = $labelWidth + $valueWidth;
        $svg = <<<SVG
<svg xmlns="http://www.w3.org/2000/svg" width="{$totalWidth}" height="20">
    <linearGradient id="smooth" x2="0" y2="100%">
        <stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
        <stop offset="1" stop-opacity=".1"/>
    </linearGradient>
    <mask id="round">
        <rect width="{$totalWidth}" height="20" rx="3" fill="#fff"/>
    </mask>
    <g mask="url(#round)">
        <rect width="{$labelWidth}" height="20" fill="#555"/>
        <rect x="{$labelWidth}" width="{$valueWidth}" height="20" fill="{$color}"/>
        <rect width="{$totalWidth}" height="20" fill="url(#smooth)"/>
    </g>
    <g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
        <text x="{$labelWidth/2}" y="15" fill="#010101" fill-opacity=".3">{$label}</text>
        <text x="{$labelWidth/2}" y="14">{$label}</text>
        <text x="{$labelWidth + $valueWidth/2}" y="15" fill="#010101" fill-opacity=".3">{$value}</text>
        <text x="{$labelWidth + $valueWidth/2}" y="14">{$value}</text>
    </g>
</svg>
SVG;
        header('Content-Type: image/svg+xml');
        echo $svg;
    }
    // 从 composer.lock 获取版本
    public static function getAppVersion($composerLockFile = 'composer.lock')
    {
        if (!file_exists($composerLockFile)) {
            return 'dev';
        }
        $lockData = json_decode(file_get_contents($composerLockFile), true);
        $rootPackage = $lockData['packages'][0] ?? null;
        if ($rootPackage && isset($rootPackage['version'])) {
            return ltrim($rootPackage['version'], 'v');
        }
        return 'unknown';
    }
}
// 使用示例
if (isset($_GET['badge']) && $_GET['badge'] === 'version') {
    $version = BadgeGenerator::getAppVersion();
    BadgeGenerator::generateSVGBadge('Version', $version);
}
?>

使用 Git 钩子自动化更新

pre-commit 钩子

#!/bin/bash
# .git/hooks/pre-commit
# 获取当前版本
VERSION=$(git describe --tags --abbrev=0 2>/dev/null || echo "0.0.0")
# 更新版本文件
cat > version.php << EOF
<?php
define('APP_VERSION', '$VERSION');
define('APP_VERSION_DATE', '$(date -u +%Y-%m-%dT%H:%M:%S)Z');
?>
EOF
git add version.php

CI/CD 集成方案

GitHub Actions 示例

# .github/workflows/version-badge.yml
name: Update Version Badge
on:
  push:
    tags:
      - 'v*'
jobs:
  update-badge:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Get version
        id: get_version
        run: echo "::set-output name=VERSION::${GITHUB_REF#refs/tags/v}"
      - name: Update version file
        run: |
          echo "<?php define('APP_VERSION', '${{ steps.get_version.outputs.VERSION }}'); ?>" > version.php
          echo "🗞️ 版本徽章已更新为 ${{ steps.get_version.outputs.VERSION }}"
      - name: Commit changes
        uses: stefanzweifel/git-auto-commit-action@v4
        with:
          commit_message: "🔖 Update version badge to ${{ steps.get_version.outputs.VERSION }}"
          branch: main

实时版本检测系统

<?php
class VersionBadgeSystem
{
    private $cacheFile = 'cache/version.json';
    public function getBadgeData()
    {
        // 检查缓存
        if (file_exists($this->cacheFile)) {
            $cached = json_decode(file_get_contents($this->cacheFile), true);
            if (time() - $cached['timestamp'] < 3600) { // 1小时缓存
                return $cached;
            }
        }
        // 获取最新版本信息
        $data = [
            'version' => $this->detectVersion(),
            'date' => date('c'),
            'commit' => $this->getLastCommit(),
            'timestamp' => time()
        ];
        // 保存缓存
        file_put_contents(
            $this->cacheFile, 
            json_encode($data, JSON_PRETTY_PRINT)
        );
        return $data;
    }
    private function detectVersion()
    {
        // 优先从 Git 获取
        if (function_exists('exec')) {
            $gitVersion = exec('git describe --tags --abbrev=0 2>/dev/null');
            if ($gitVersion) {
                return ltrim($gitVersion, 'v');
            }
        }
        // 回退到 composer.json
        if (file_exists('composer.json')) {
            $composer = json_decode(file_get_contents('composer.json'), true);
            if (isset($composer['version'])) {
                return $composer['version'];
            }
        }
        return 'dev-master';
    }
    private function getLastCommit()
    {
        if (function_exists('exec')) {
            return exec('git log -1 --format="%h" 2>/dev/null');
        }
        return 'none';
    }
    public function renderBadge()
    {
        $badge = new BadgeGenerator();
        $data = $this->getBadgeData();
        return $badge->generateSVGBadge(
            'Version', 
            $data['version'],
            $this->getVersionColor($data['version'])
        );
    }
    private function getVersionColor($version)
    {
        if (preg_match('/^\d+\.\d+\.\d+$/', $version)) {
            return '#4c1';  // 稳定版 - 绿色
        } elseif (preg_match('/^[0-9]+\.[0-9]+\.\d+-[a-z0-9]+$/i', $version)) {
            return '#97ca00'; // 预发布 - 黄绿色
        }
        return '#fe7d37'; // 开发版本 - 橙色
    }
}
// 使用
$badgeSystem = new VersionBadgeSystem();
$badgeSystem->renderBadge();
?>

集成到 README 自动更新脚本

<?php
// update_readme_badge.php
class ReadmeBadgeUpdater
{
    public function update()
    {
        $version = $this->getCurrentVersion();
        $readmeFile = 'README.md';
        if (!file_exists($readmeFile)) {
            die("README.md 不存在\n");
        }
        $content = file_get_contents($readmeFile);
        // 替换版本徽章标记
        $pattern = '/\[![Vv]ersion\].*?\)/';
        $replacement = "[![Version](https://img.shields.io/badge/version-{$version}-blue)]";
        $newContent = preg_replace($pattern, $replacement, $content);
        if ($newContent !== $content) {
            file_put_contents($readmeFile, $newContent);
            echo "✅ README.md 版本徽章已更新到 v{$version}\n";
        } else {
            echo "ℹ️ 版本无变化,无需更新\n";
        }
    }
    private function getCurrentVersion()
    {
        // 从 Git tag 获取
        if (function_exists('exec')) {
            $tag = exec('git describe --tags $(git rev-list --tags --max-count=1) 2>/dev/null');
            if ($tag) {
                return ltrim($tag, 'v');
            }
        }
        // 从 composer.json 获取
        $composer = json_decode(file_get_contents('composer.json'), true);
        return $composer['version'] ?? '0.1.0';
    }
}
// 执行更新
$updater = new ReadmeBadgeUpdater();
$updater->update();
?>

现代化解决方案

推荐组合方案:

  1. Shields.io + Packagist 最简单,自动维护
  2. GitHub Actions 自动化构建和版本徽章更新
  3. 自定义 SVG 生成器 需要完全自己控制时
  4. Badge 缓存系统 需要高并发时

最佳实践是在 CI/CD 流程中集成版本徽章更新,这样既自动化又准确可靠。

抱歉,评论功能暂时关闭!