本文目录导读:

- 📚 目录导读
- 为什么要做变更日志?——不只是给用户看
- 基础篇:手动生成变更日志(PHP 数组 + Markdown)
- 进阶篇:基于 Git 自动生成(提取 Commit 信息)
- 高级篇:使用开源工具(如
conventional-changelog) - 实战问答:关于版本号的哲学(SemVer)
- 构建你的专属工作流
PHP 怎么生成变更日志?从零到自动化,构建专业的 CHANGELOG 工作流**
📚 目录导读
- 为什么要做变更日志? —— 不只是给用户看
- 基础篇:手动生成变更日志(PHP 数组 + Markdown)
- 进阶篇:基于 Git 自动生成(提取 Commit 信息)
- 高级篇:使用开源工具(如
conventional-changelog) - 实战问答:关于版本号的哲学(SemVer)
- 构建你的专属工作流
为什么要做变更日志?——不只是给用户看
很多 PHP 开发者认为生成 CHANGELOG 只是给最终用户看“修了什么 Bug”,但实际上,变更日志是给未来的你(以及你的同事)看的一份“开发日记”。
在快速的迭代中,如果你不记录变更,三个月后你甚至不知道某段复杂逻辑为何存在,对于 SEO(谷歌/必应)而言,高质量的文档站点(包含结构化变更记录)能提高技术博客的权威性,间接拉升关键词排名,本文不讨论复杂的高深理论,而是给出 3 种在 PHP 项目中立即可用的方案。
基础篇:手动生成变更日志(PHP 数组 + Markdown)
这是最快捷的办法,无需任何依赖,适合个人项目或小型团队,逻辑很简单:编写一个 PHP 脚本,将变更信息存入数组,然后批量渲染为 Markdown 文件。
代码思路(generate-changelog.php):
<?php
$changes = [
[ 'version' => '1.2.0', 'date' => '2025-04-10', 'items' => [
'Added' => '新增用户积分系统',
'Fixed' => '修复了登录页面的 XSS 漏洞',
]],
[ 'version' => '1.1.0', 'date' => '2025-03-22', 'items' => [
'Changed' => '重构了 API 层,速度提升 20%',
]],
];
$output = "# 变更日志\n\n";
foreach ($changes as $release) {
$output .= "## [{$release['version']}] - {$release['date']}\n";
foreach ($release['items'] as $type => $desc) {
$output .= "- **{$type}**: {$desc}\n";
}
$output .= "\n";
}
file_put_contents('CHANGELOG.md', $output);
echo "已生成 CHANGELOG.md";
优缺点:
- 优点:零成本,完全可控格式。
- 缺点:容易忘记更新,无法与代码同步。
进阶篇:基于 Git 自动生成(提取 Commit 信息)
这是目前最推荐的做法,利用 Git 钩子(Hook)或 PHP 的 exec() 函数,自动提取最近提交的记录,并按类型(feat、fix、docs)分类。
核心原理: 利用 git log 命令获取结构化数据。
<?php
// 执行 git 命令,获取最近 20 条提交
exec('git log --pretty=format:"%h|%s|%an|%ad" --date=short -20', $output);
$entries = [];
foreach ($output as $line) {
[$hash, $subject, $author, $date] = explode('|', $line);
// 通过正则匹配前缀来分类
if (preg_match('/^feat(\(.*\))?:/', $subject)) {
$type = 'Added';
} elseif (preg_match('/^fix(\(.*\))?:/', $subject)) {
$type = 'Fixed';
} else {
$type = 'Misc';
}
$entries[$date][] = "- **{$type}** - {$subject} (`{$hash}`)";
}
// 生成 Markdown
ksort($entries); // 按日期排序
// ...(后续渲染逻辑同基础篇)
关键点: 这要求你的 Git 提交信息必须遵循 Conventional Commits 规范(如 feat: 增加功能),这在 PHP 社区(如 Laravel)中已是标配。
高级篇:使用开源工具(如 conventional-changelog)
如果你不想写上述繁琐的正则逻辑,直接使用 Node.js 生态的工具(但你可以在 PHP 中通过 shell_exec 调用)。
# 在项目根目录执行 npx conventional-changelog -p angular -i CHANGELOG.md -s -r 0
PHP 代码内触发执行:
<?php $cmd = 'npx conventional-changelog -p angular -i CHANGELOG.md -s'; $result = shell_exec($cmd); echo "工具执行完毕,文件已更新。";
为什么要这么做?
- 标准化:Angular 团队维护的规范,会被 Google 收录时更容易被识别为结构化数据。
- 自动升级版本:配合
semver自动判断大、中、小版本号。
注意: 该方法虽然强大,但需要 Node 环境,并不是纯 PHP 方案,对于国内主机环境,建议看清是否支持 Shell 函数。
实战问答:关于版本号的哲学(SemVer)
问:如何确定是 0.0 还是 1.0?
答: 这就是 语义化版本(SemVer)的范畴,规则如下:
- 主版本(Major):做了不兼容的 API 修改(比如删除了某个古老函数)。
- 次版本(Minor):向后兼容的功能性新增(比如给类加了新方法)。
- 修订号(Patch):向后兼容的问题修正(修了个 parse 的 Bug)。
问:是否建议每次发版都生成一份新的 CHANGELOG?
答: 绝对不建议。建议每次 Commit 时,如果是重要功能,就顺带更新 CHANGELOG,但更合理的是,在 Git 打 Tag(标签)时,强制生成一份该版本对应的日志,把生成脚本挂载在 Git Hook(post-commit 或 pre-tag)上。
构建你的专属工作流
无论你选择哪种方案,核心目的是让 CHANGELOG 成为项目的一部分,而不是文档的负担。
推荐的 PHP 项目工作流:
- 本地开发:提交代码时,遵循
feat/fix/docs前缀。 - 开发环境:利用 进阶篇 的 PHP 脚本,自动生成最新的
CHANGELOG.md草案。 - 发版前:人工审查草案,补充遗漏的上下文说明(为什么改”),调整版本号。
- 发版:执行
git tag,此时生成最终版 CHANGELOG。
针对 SEO(必应/谷歌)的最后建议: 如果你将 CHANGELOG 发布为网页,确保 URL 中带关键字(yourdomain.com/changelog),并且在页面中使用语义化的 HTML 标签(<h2> 包版本号,<time> 属性标记日期),这能让搜索引擎更好地理解你的文档结构。
马上打开你的 php -v 终端,用这 20 行代码,彻底告别垃圾日志吧!