jfcherng/php-diff
A comprehensive library for generating differences between two strings in multiple formats (unified, side by side HTML etc).
Maintainers
Fund package maintenance!
Requires
- php: >=8.3
- jfcherng/php-color-output: ^3
- jfcherng/php-mb-string: ^1.4.6 || ^2
- jfcherng/php-sequence-matcher: ^5
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.94
- phan/phan: ^6
- phpunit/phpunit: ^12
- squizlabs/php_codesniffer: ^4.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
BSD-3-Clause 38bd25b2ca59e2fe0d8dd209b5557ca193b73a43
- Jack Cherng <jfcherng.woop@gmail.com>
- Chris Boulton <chris.boulton.woop@interspire.com>
This package is auto-updated.
Last update: 2026-06-22 13:33:26 UTC
README
ð GitHub Workflow Status (branch)
ð Codacy grade
ð Packagist
ð Packagist Version
ð Project license
ð GitHub stars
ð Donate to this project using Paypal
A comprehensive library for generating diff between two strings.
Introduction
Generated diff can be rendered in all of the standard formats including:
Text renderers:
- Context
- Json (plain text)
- Unified
HTML renderers:
- Combined
- Inline
- Json (HTML)
- Side by Side
Note that for HTML rendered results, you have to add CSS for a better visualization.
You may modify one from example/diff-table.css or write your own from zero.
If you are okay with the default CSS, there is \Jfcherng\Diff\DiffHelper::getStyleSheet()
which can be used to get the content of the example/diff-table.css.
Requirements
Installation
This package is available on Packagist by the name of jfcherng/php-diff.
composer require jfcherng/php-diff
Example
See files and readme in the example/ directory.
<?php include __DIR__ . '/vendor/autoload.php'; use Jfcherng\Diff\Differ; use Jfcherng\Diff\DiffHelper; use Jfcherng\Diff\Factory\RendererFactory; use Jfcherng\Diff\Options\DifferOptions; use Jfcherng\Diff\Options\RendererOptions; use Jfcherng\Diff\Renderer\RendererConstant; $oldFile = __DIR__ . '/example/old_file.txt'; $newFile = __DIR__ . '/example/new_file.txt'; $old = 'This is the old string.'; $new = 'And this is the new one.'; // renderer class name: // Text renderers: Context, JsonText, Unified // HTML renderers: Combined, Inline, JsonHtml, SideBySide $rendererName = 'Unified'; // the Differ options $differOptions = new DifferOptions( // show how many neighbor lines; Differ::CONTEXT_ALL shows the whole file context: 3, // ignore case difference ignoreCase: false, // ignore line ending difference ignoreLineEnding: false, // ignore whitespace difference ignoreWhitespace: false, // if the input sequence is too long, give up (especially for char-level diff) lengthLimit: 2000, // when inputs are identical, render the whole content rather than an empty result fullContextIfIdentical: false, ); // the renderer options $rendererOptions = new RendererOptions( // how detailed the rendered HTML in-line diff is? (none, line, word, char) detailLevel: 'line', // renderer language: eng, cht, chs, jpn, ... // or an array which has the same keys with a language file // check the "Custom Language" section in the readme for more advanced usage language: 'eng', // show line numbers in HTML renderers lineNumbers: true, // show a separator between different diff hunks in HTML renderers separateBlock: true, // show the (table) header showHeader: true, // render spaces/tabs as <span class="ch sp"> </span> tags (visualised via CSS) spaceToHtmlTag: false, // convert consecutive spaces to in HTML output spacesToNbsp: false, // HTML renderer tab width (negative = do not convert into spaces) tabSize: 4, // Combined renderer: merge replace-blocks whose changed ratio is at or below this threshold (0â1) mergeThreshold: 0.8, // Unified/Context renderers CLI colorization: // RendererConstant::CLI_COLOR_AUTO = colorize if possible (default) // RendererConstant::CLI_COLOR_ENABLE = force colorize // RendererConstant::CLI_COLOR_DISABLE = force no color cliColorization: RendererConstant::CLI_COLOR_AUTO, // JSON renderer: emit op tags as human-readable strings instead of ints outputTagAsString: false, // JSON renderer: flags passed to json_encode() // see https://www.php.net/manual/en/function.json-encode.php jsonEncodeFlags: \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE, // word-level diff: adjacent segments joined by these characters are merged into one // e.g. "<del>good</del>-<del>looking</del>" â "<del>good-looking</del>" wordGlues: ['-', ''], // return this string verbatim when the two inputs are identical; null = renderer default resultForIdenticals: null, // extra CSS classes added to the diff container <div> in HTML renderers wrapperClasses: ['diff-wrapper'], ); // one-line simply compare two files $result = DiffHelper::calculateFiles($oldFile, $newFile, $rendererName, $differOptions, $rendererOptions); // one-line simply compare two strings $result = DiffHelper::calculate($old, $new, $rendererName, $differOptions, $rendererOptions); // or even shorter if you are happy with default options $result = DiffHelper::calculate($old, $new, $rendererName); // custom usage $differ = new Differ(explode("\n", $old), explode("\n", $new), $differOptions); $renderer = RendererFactory::make($rendererName, $rendererOptions); // or your own renderer object $result = $renderer->render($differ); // use the JSON result to render in HTML $jsonResult = DiffHelper::calculate($old, $new, 'Json'); // may store the JSON result in your database $htmlRenderer = RendererFactory::make('Inline', $rendererOptions); $result = $htmlRenderer->renderArray(json_decode($jsonResult, true));
Rendered Results
HTML Diff In-line Detailed Rendering
| None-level | Line-level (Default) |
|---|---|
| ð Image |
ð Image |
| Word-level | Char-level |
| ð Image |
ð Image |
Renderer: Inline
<?php $rendererOptions = ['detailLevel' => 'line'];
Renderer: Side By Side
<?php $rendererOptions = ['detailLevel' => 'line'];
Renderer: Combined
<?php $rendererOptions = ['detailLevel' => 'word'];
This renderer is suitable for articles and always has no line number information.
Renderer: Unified
About the Unified diff format: https://en.wikipedia.org/wiki/Diff#Unified_format
@@ -1,3 +1,4 @@ -<p>Hello World!</p> +<div>Hello World!</div> ~~~~~~~~~~~~~~~~~~~ +Let's add a new line here. X @@ -7,6 +8,5 @@ N -Do you know in Chinese, "éæ§éį―é " means tuna can. +Do you know in Japanese, "éãŪįžķčа" means fish can. This is just a useless line. G -// remember to delete this line Say hello to my neighbors.
Renderer: Context
About the Context diff format: https://en.wikipedia.org/wiki/Diff#Context_format
Renderer: Text JSON
This renderer has no detailed diff.
Renderer: HTML JSON
For a "tag": "rep" (8) block, this renderer has HTML-style detailed diff.
If you don't need those detailed diff, consider using the JsonText renderer.
Custom Language
Override an Existing Language
If you just want to override some translations of an existing language...
$rendererOptions = [ 'language' => [ // use English as the base language 'eng', // your custom overrides [ // use "Diff" as the new value of the "differences" key 'differences' => 'Diff', ], // maybe more overrides if you somehow need them... ], ]
Acknowledgment
This package is built on the top of chrisboulton/php-diff initially. But the original repository looks like no longer maintained. Here have been quite lots of rewrites and new features since then, hence I re-started this as a new package for better visibility.
