alto/code-diff
Composer 安装命令:
composer require alto/code-diff
包简介
Generate, render and apply code diffs. Myers algorithm, versatile rendering (HTML, JSON, ANSI), and full patching support.
README 文档
README
A modern PHP library to generate, render and apply diffs, featuring advanced algorithms, versatile rendering, and full patching support.
Features
Advanced Diff Algorithms
- Myers Diff Algorithm (default): Fast and accurate line-by-line and word-by-word diffing (O(ND)).
- LCS Diff Algorithm: Opt-in Longest Common Subsequence engine (O(MN) time and memory) for deterministic academic use cases.
- Binary Detection: Automatic detection and rejection of binary content.
Versatile Rendering
Visualize and format diffs for any output medium:
HTML Output
ANSI Side-by-Side
Full Patching Support
- Unified Diff Parsing: Parse standard unified diff patches into objects.
- Patch Application: Apply patches to files with "fuzz" factor support.
- Multi-file Bundles: Handle complex patches affecting multiple files.
Requirements
- PHP 8.3 or higher
Installation
composer require alto/code-diff
Quick Start
Basic Diff
use Alto\Code\Diff\Diff; use Alto\Code\Diff\Renderer\UnifiedRenderer; $old = "line1\nline2\nline3\n"; $new = "line1\nline2 modified\nline3\n"; $result = Diff::build()->compare($old, $new); $renderer = new UnifiedRenderer('old.txt', 'new.txt'); echo $renderer->render($result);
Output:
--- old.txt +++ new.txt @@ -1,3 +1,3 @@ line1 -line2 +line2 modified line3
Word-Level Diff
$result = Diff::build() ->withWordDiff() ->compare($old, $new);
HTML Output
use Alto\Code\Diff\Renderer\HtmlRenderer; $renderer = new HtmlRenderer( showLineNumbers: true, wrapLines: false, classPrefix: 'diff-' ); echo $renderer->render($result);
JSON Output
use Alto\Code\Diff\Renderer\JsonRenderer; $renderer = new JsonRenderer(prettyPrint: true); echo $renderer->render($result);
ANSI Side-by-Side Output
use Alto\Code\Diff\Renderer\AnsiSideBySideRenderer; $renderer = new AnsiSideBySideRenderer( showLineNumbers: true, width: 120 ); echo $renderer->render($result);
Configuration Options
Context Lines
Control how many unchanged lines to show around changes:
$result = Diff::build() ->contextLines(5) // Default is 3 ->compare($old, $new);
Ignore Whitespace
Ignore whitespace differences:
$result = Diff::build() ->ignoreWhitespace() ->compare($old, $new);
Size Limits
Set maximum input size (default 5MB):
$result = Diff::build() ->maxBytes(10_000_000) // 10MB ->compare($old, $new);
Parsing and Applying Patches
Parse a Unified Diff
use Alto\Code\Diff\Patch\UnifiedParser; $patch = <<<'PATCH' --- old.txt +++ new.txt @@ -1,3 +1,3 @@ line1 -line2 +line2 modified line3 PATCH; $parser = new UnifiedParser(); $bundle = $parser->parse($patch); foreach ($bundle->files() as $file) { echo "File: {$file->oldPath} -> {$file->newPath}\n"; echo "Hunks: " . count($file->result->hunks()) . "\n"; }
Apply a Patch
use Alto\Code\Diff\Patch\PatchApplier; $original = "line1\nline2\nline3\n"; $applier = new PatchApplier(); $patched = $applier->apply($original, $patch); echo $patched; // Output: line1\nline2 modified\nline3\n
Note:
PatchApplier::apply()accepts a single-file patch. For multi-file diffs, parse the patch and callapplyBundle()instead.
Apply Patch with Fuzz Factor
$applier = new PatchApplier(fuzz: 2); $patched = $applier->apply($original, $patch);
Apply Patch to Multiple Files
use Alto\Code\Diff\Model\DiffBundle; $files = [ 'file1.txt' => "content1\n", 'file2.txt' => "content2\n", ]; $applier = new PatchApplier(); $patchedFiles = $applier->applyBundle($files, $bundle);
Emitting Unified Diffs
From DiffResult
use Alto\Code\Diff\Patch\UnifiedEmitter; $result = Diff::build()->compare($old, $new); $emitter = new UnifiedEmitter(); $patch = $emitter->emit($result);
From DiffBundle
use Alto\Code\Diff\Model\DiffBundle; use Alto\Code\Diff\Model\DiffFile; $files = [ new DiffFile('file1.txt', 'file1.txt', $result1), new DiffFile('file2.txt', 'file2.txt', $result2), ]; $bundle = new DiffBundle($files); $emitter = new UnifiedEmitter(); $patch = $emitter->emit($bundle);
Renderer Options
UnifiedRenderer
new UnifiedRenderer( oldLabel: 'a/file.txt', // Label for old version newLabel: 'b/file.txt' // Label for new version );
HtmlRenderer
new HtmlRenderer( showLineNumbers: true, // Show line numbers wrapLines: false, // Wrap long lines classPrefix: 'diff-' // CSS class prefix );
JsonRenderer
new JsonRenderer( prettyPrint: true // Format with indentation );
AnsiSideBySideRenderer
new AnsiSideBySideRenderer( showLineNumbers: true, // Show line numbers width: 120 // Terminal width );
Advanced Usage
Custom Diff Engine
You can choose between the built-in engines or implement your own.
MyersDiffEngine (Default): Uses the O(ND) Myers algorithm. Best for most use cases, especially when differences are small.
LcsDiffEngine:
Uses the standard O(MN) LCS algorithm. Enable it explicitly with ->withEngine(new LcsDiffEngine()) only for small inputs, because its quadratic memory footprint is intended for controlled, academic scenarios.
use Alto\Code\Diff\Engine\LcsDiffEngine; $result = Diff::build() ->withEngine(new LcsDiffEngine()) ->compare($old, $new);
Implementing a Custom Engine
use Alto\Code\Diff\Engine\DiffEngineInterface; class MyCustomEngine implements DiffEngineInterface { public function diff(string $old, string $new, Options $opts): DiffResult { // Custom implementation } } $result = Diff::build() ->withEngine(new MyCustomEngine()) ->compare($old, $new);
Working with Git Patches
The library supports parsing git-style unified diffs with headers:
$patch = <<<'PATCH' diff --git a/file.txt b/file.txt index abcdef..123456 100644 --- a/file.txt +++ b/file.txt @@ -1,3 +1,3 @@ line1 -line2 +line2 modified line3 PATCH; $parser = new UnifiedParser(); $bundle = $parser->parse($patch); // Access headers $file = $bundle->files()[0]; $file->headers['diff']; // 'diff --git a/file.txt b/file.txt' $file->headers['index']; // 'index abcdef..123456 100644'
Documentation
For more detailed information, please refer to the documentation in the docs/ directory:
- API Reference
- Architecture
- Basic Text Comparison
- File Comparison
- Git Integration
- Patch Operations
- Rendering Options
- Advanced Scenarios
- Examples
Testing
Run the test suite:
vendor/bin/phpunit
Run tests with coverage:
vendor/bin/phpunit --coverage-text
License
This project is licensed under the MIT License.
alto/code-diff 适用场景与选型建议
alto/code-diff 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 6 次下载、GitHub Stars 达 3, 最近一次更新时间为 2026 年 01 月 04 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「json」 「html」 「diff」 「Rendering」 「formatting」 「patch」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 alto/code-diff 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 alto/code-diff 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 alto/code-diff 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Texy converts plain text in easy to read Texy syntax into structurally valid (X)HTML. It supports adding of images, links, nested lists, tables and has full support for CSS. Texy supports hyphenation of long words (which reflects language rules), clickable emails and URL (emails are obfuscated again
A library for comparing two HTML files/snippets and highlighting the differences using simple HTML.
Kinikit - PHP Application development framework MVC component
Schema Diff: Show difference between MySQL databases
ext-json wrapper with sane defaults
统计信息
- 总下载量: 6
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 3
- 点击次数: 41
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-01-04