boulzy/array-comparator
Compare PHP arrays with boulzy/array-comparator: detect differences and changes between two arrays, including nested structures. Useful for testing, syncing data, and debugging by quickly showing what was added, removed, or modified.
Installation
composer require boulzy/array-comparator
No additional configuration is required—just autoload the package.
Basic Usage Import the comparator and use it to compare two arrays:
use Boulzy\ArrayComparator\ArrayComparator;
$array1 = ['a' => 1, 'b' => 2];
$array2 = ['a' => 1, 'b' => 3];
$comparator = new ArrayComparator();
$result = $comparator->compare($array1, $array2);
The $result will be an associative array showing differences (e.g., ['b' => ['expected' => 2, 'actual' => 3]]).
First Use Case: Data Validation Compare user-submitted data against expected values (e.g., API payloads, form inputs):
$expected = ['name' => 'John', 'age' => 30];
$submitted = ['name' => 'John', 'age' => 25];
$differences = $comparator->compare($expected, $submitted);
if (!empty($differences)) {
// Log or reject invalid data
}
Deep Comparison
Use compare() with nested arrays to validate complex structures:
$config = ['database' => ['host' => 'localhost', 'port' => 3306]];
$userConfig = ['database' => ['host' => 'localhost', 'port' => 3307]];
$comparator->compare($config, $userConfig);
Custom Matching Functions Override default comparison logic for specific keys:
$comparator->setMatchingFunction('price', function ($expected, $actual) {
return abs($expected - $actual) < 0.01; // Allow floating-point tolerance
});
Integration with Laravel Validation Use the comparator to pre-validate arrays before passing to Laravel’s validator:
$differences = $comparator->compare($expectedSchema, $input);
if ($differences) {
throw new \InvalidArgumentException("Invalid data: " . json_encode($differences));
}
Testing Assert array equality in PHPUnit:
$this->assertEmpty($comparator->compare($expected, $actual));
Diff Generation Use the comparator to generate human-readable diffs for logs/debugging:
$diff = $comparator->getDiff($array1, $array2);
Partial Comparisons Compare only specific keys to optimize performance:
$comparator->compare($array1, $array2, ['key1', 'key2']);
Callback-Based Comparisons Dynamically define comparison rules per use case:
$comparator->setMatchingFunction('metadata', function ($a, $b) {
return array_diff_assoc($a, $b) === [];
});
Strict Typing
The comparator uses strict comparison (===). Ensure types match (e.g., 1 vs "1" will fail).
Fix: Cast values explicitly or use setLooseComparison(true).
Nested Array Handling
By default, nested arrays are compared recursively. If you have circular references or non-traversable objects, the comparator may throw errors.
Fix: Use setMaxDepth() to limit recursion or implement a custom ArrayAccess wrapper.
Key Order Sensitivity Associative arrays are compared by keys, not order. If order matters, pre-sort arrays or use a custom matching function.
Performance with Large Arrays
Deep comparisons on large arrays (e.g., 10,000+ elements) can be slow.
Fix: Compare only relevant keys or use compareShallow() for top-level checks.
Enable Verbose Output
Use setVerbose(true) to log comparison steps for debugging:
$comparator->setVerbose(true);
$result = $comparator->compare($array1, $array2);
Inspect Differences
The getDiff() method returns a detailed breakdown of mismatches, including:
expected: The value from the first array.actual: The value from the second array.path: The nested key path (e.g., ['user', 'address', 'city']).Custom Exceptions
Catch Boulzy\ArrayComparator\Exception\ComparisonException for invalid inputs (e.g., non-array arguments).
Custom Matching Functions Register global or per-key functions to override default behavior:
$comparator->setMatchingFunction('timestamps', function ($a, $b) {
return strtotime($a) === strtotime($b);
});
Pre/Post-Processing
Use setArrayNormalizer() to transform arrays before comparison (e.g., normalize dates):
$comparator->setArrayNormalizer(function ($array) {
return array_map('strtolower', $array);
});
Integration with Laravel Create a macro for global use in your app:
use Illuminate\Support\Facades\Blade;
Blade::macro('compareArrays', function ($a, $b) {
return (new ArrayComparator())->compare($a, $b);
});
Testing Edge Cases Test with:
null/false values.array/object inputs (use json_decode(json_encode($obj), true) for consistency).How can I help you explore Laravel packages today?