Installation:
composer require caxy/htmldiff-bundle
Register the bundle in config/bundles.php (Symfony 4+):
return [
// ...
Caxy\HtmlDiffBundle\CaxyHtmlDiffBundle::class => ['all' => true],
];
First Use Case: Generate a diff between two HTML strings in a controller:
use Caxy\HtmlDiffBundle\HtmlDiff;
class DiffController extends AbstractController {
public function showDiff(string $oldHtml, string $newHtml): Response {
$diff = new HtmlDiff();
$result = $diff->diff($oldHtml, $newHtml);
return $this->render('diff/show.html.twig', ['diff' => $result]);
}
}
Twig Integration (if using Symfony):
Add the Twig extension to config/packages/twig.yaml:
twig:
extensions:
- Caxy\HtmlDiffBundle\Twig\HtmlDiffExtension
Use in templates:
{{ html_diff(oldHtml, newHtml) }}
Generating Diffs:
$diff = new \Caxy\HtmlDiffBundle\HtmlDiff();
$diff->setOptions([
'ignoreWhitespace' => true, // Ignore whitespace changes
'ignoreCase' => true, // Case-insensitive comparison
]);
$result = $diff->diff($oldHtml, $newHtml);
setOptions() for fine-grained control (e.g., ignoreAttributes, ignoreTags).Integration with Forms: Compare rendered form HTML for A/B testing or regression checks:
$form1 = $this->createForm(FormType::class);
$form2 = $this->createForm(ModifiedFormType::class);
$diff = $htmlDiff->diff($form1->createView()->renderBlock('widget'), $form2->createView()->renderBlock('widget'));
API Responses: Return diffs as JSON for frontend processing:
return $this->json([
'diff' => $htmlDiff->diff($oldHtml, $newHtml),
'status' => 'generated',
]);
Command-Line Usage: Create a console command for CLI diffs:
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class GenerateDiffCommand extends Command {
protected function execute(InputInterface $input, OutputInterface $output) {
$oldHtml = file_get_contents($input->getArgument('old-file'));
$newHtml = file_get_contents($input->getArgument('new-file'));
$diff = $this->getHtmlDiff()->diff($oldHtml, $newHtml);
$output->write($diff);
}
private function getHtmlDiff(): HtmlDiff {
return new HtmlDiff();
}
}
Event Listeners: Hook into kernel events to auto-diff HTML responses (e.g., for testing):
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
class DiffListener {
public function onKernelResponse(ResponseEvent $event) {
if ($event->isMasterRequest()) {
$diff = $this->getHtmlDiff()->diff(
$event->getRequest()->get('old_html', ''),
$event->getResponse()->getContent()
);
// Log or store diff for comparison
}
}
}
Performance:
ignoreWhitespace and ignoreAttributes to optimize.memory_limit or process in chunks.False Positives:
$cleanHtml = preg_replace('/<div class="dynamic">.*?<\/div>/s', '', $html);
ignoreWhitespace unless you need exact whitespace diffs.Configuration Quirks:
config/bundles.php. No manual AppKernel edits are needed.twig.yaml.Edge Cases:
use Symfony\Component\DomCrawler\Crawler;
$cleanHtml = (new Crawler($html))->html();
$diff = new HtmlDiff();
$diff->setOptions(['debug' => true]); // Logs options and input
file_put_contents('debug_old.html', $oldHtml);
file_put_contents('debug_new.html', $newHtml);
php bin/console cache:clear
Custom Diff Renderer: Override the default renderer for custom output formats:
use Caxy\HtmlDiffBundle\Renderer\HtmlDiffRendererInterface;
class CustomRenderer implements HtmlDiffRendererInterface {
public function render(array $diff): string {
// Custom logic (e.g., Markdown, JSON)
return json_encode($diff);
}
}
Register it in services.yaml:
services:
Caxy\HtmlDiffBundle\HtmlDiff:
arguments:
$renderer: '@custom.renderer'
Pre/Post-Processing:
Extend the HtmlDiff class to add hooks:
class ExtendedHtmlDiff extends HtmlDiff {
public function diff(string $oldHtml, string $newHtml): string {
$oldHtml = $this->preProcess($oldHtml);
$newHtml = $this->preProcess($newHtml);
return parent::diff($oldHtml, $newHtml);
}
private function preProcess(string $html): string {
// Strip non-critical elements
return preg_replace('/<script>.*?<\/script>/s', '', $html);
}
}
Symfony Messenger Integration: Use the Messenger component to queue diff jobs for async processing:
use Symfony\Component\Messenger\MessageBusInterface;
class DiffService {
public function __construct(private MessageBusInterface $bus) {}
public function queueDiff(string $oldHtml, string $newHtml) {
$this->bus->dispatch(new DiffMessage($oldHtml, $newHtml));
}
}
How can I help you explore Laravel packages today?