codeigniter 无内置 diff 功能,需用 xdiff 扩展生成标准 diff 文本或 array_diff 做行级粗略比对,注意路径、权限、xss 防护及语义差异场景选择。

diff、xdiff 或 PHP 原生 array_udiff 那样的语义比对能力。如果你在控制器或模型里直接用 file_get_contents() 读两个文件再用 == 判断是否相等——那只能做「全等校验」,不是「差异对比」。
要真正看到「哪几行变了、删了、加了」,得靠外部工具或手动组合 PHP 基础函数。下面分场景说清楚怎么做、为什么这么选、容易掉坑在哪。
用 PHP 的 xdiff_file_diff() 生成可读 diff 文本
这是最接近 Unix diff 行为的方式,但前提是服务器已安装 xdiff 扩展(非默认启用)。
- 确认扩展可用:
php -m | grep xdiff;若无,需编译安装或联系运维开启 -
xdiff_file_diff($old_file, $new_file, $output_file)会写入标准 diff 格式(含@@ -1,3 +1,4 @@行) - 注意路径必须是服务端绝对路径,不能传 URL 或 CI 的
APPPATH别名字符串(得先realpath(APPPATH.'../uploads/old.txt')) - 输出文件需有写权限,且不要放在 Web 可访问目录下(避免泄露原始内容)
不用扩展:用 array_diff() 做行级粗略比对
适合快速判断「新增了哪些行」「删除了哪些行」,但不保留顺序、不标变化位置,也不处理空格/大小写敏感问题。
- 先按行读取:
$a = file($file_a, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) -
$added = array_diff($b, $a)得到只在新文件中出现的行(去重后) -
$removed = array_diff($a, $b)得到只在旧文件中出现的行 - ⚠️ 问题:如果某行前后多一个空格、换行符不同、或大小写不一致,就会被当作不同行——这不是 diff,是集合差集
- 如需忽略空格,得提前
array_map('trim', $a),但会丢失原始格式信息
在视图中安全渲染 diff 结果(防 XSS)
无论用哪种方式生成的 diff 输出,若要展示在页面上,必须过滤 HTML 特殊字符,否则攻击者可注入脚本。
- 别直接
echo $diff_output——、<code>>、&会被浏览器解析 - 用
htmlentities($diff_output, ENT_QUOTES, 'UTF-8')转义后再nl2br()换行 - 若想高亮显示(+ 绿 / – 红),建议用前端库如
diff2html,后端只返回纯文本 diff,由 JS 渲染——更安全也更可控 - CI 的
esc()辅助函数仅适用于简单变量,对多行 diff 内容不够鲁棒,不推荐依赖
数据库字段值变更记录怎么比?别现场 diff 文件
很多用户实际想解决的是「表单提交后,哪些字段被改了」,这和文件 diff 是两回事——应该在模型层做键值比对,而不是把整条记录存成文件再 diff。
- 查出原记录:
$original = $this->db->get_where('posts', ['id' => $id])->row_array() - 拿到新数据:
$updated = $this->input->post() - 用
array_diff_assoc($updated, $original)找出键值对变化项(保留键名) - 注意:
NULL和空字符串''在 PHP 中不等价,array_diff_assoc会严格区分,这点常被忽略 - 若字段含 JSON 或序列化内容,需先
json_decode()或unserialize()再比,否则只是字符串字面量对比











