Understanding PHP's array_udiff() Function
Learn how PHP's array_udiff() compares arrays using a user-defined callback and returns values found only in the first array. Examples with numbers and objects.
array_udiff() computes the difference between arrays by comparing their values with a callback function that you supply. It returns the values present in the first array that are not found in any of the other arrays. The "u" in the name stands for user-defined — unlike array_diff(), which compares values as strings, array_udiff() lets you decide exactly when two values count as "equal".
This page covers the function's syntax, how the callback works, runnable examples with numbers and objects, and the common gotchas to watch for.
When would you use array_udiff()?
Reach for array_udiff() whenever the default comparison in array_diff() is too crude:
- Objects.
array_diff()converts each value to a string. Objects without a__toString()method cannot be compared that way, so you need a callback that inspects a property instead. - Custom equality. You want a case-insensitive comparison, a comparison by a single field, or a tolerance-based numeric comparison.
- Mixed or normalized data. You want to treat
"5",5, and5.0as the same value, or compare floats with rounding.
If you only need plain string comparison, prefer the simpler array_diff().
How array_udiff() works
The function takes two or more arrays, with the last argument being the comparison callback. It returns an array of the values from the first array that the callback does not find equal to any value in the later arrays. Keys and order from the first array are preserved.
Syntax
array_udiff(array $array1, array $array2, array ...$arrays, callable $value_compare_func): arrayarray $array1— the array whose values are returned (the "base" array).array $array2— an array to compare against.array ...$arrays— any number of additional arrays to compare against.callable $value_compare_func— the comparison callback. It is always the last argument.
The comparison callback
The callback receives two values and must return an integer:
- a number less than 0 if the first value is "smaller",
- 0 if the two values are considered equal,
- a number greater than 0 if the first value is "larger".
Returning 0 is what marks two values as equal, so a value in $array1 is excluded from the result whenever the callback returns 0 for it against some value in a later array. The < 0 / > 0 results let PHP sort the values internally for an efficient comparison — getting them right matters, so don't just return 0 or 1. The spaceship operator (<=>) is the easiest correct way to produce this value.
Example 1: comparing two arrays of numbers
This example uses a named function as the callback to find numbers that are in $array1 but not in $array2:
<?php
function compare_numbers($a, $b) {
if ($a == $b) {
return 0;
} elseif ($a < $b) {
return -1;
} else {
return 1;
}
}
$array1 = [1, 2, 3, 4, 5];
$array2 = [2, 4, 6];
$result = array_udiff($array1, $array2, 'compare_numbers');
print_r($result);
?>compare_numbers() returns 0 whenever two values match, so the matching numbers (2 and 4) are removed. The result keeps the original keys from $array1:
Array
(
[0] => 1
[2] => 3
[4] => 5
)The whole callback could be replaced with a one-liner using the spaceship operator: fn($a, $b) => $a <=> $b.
Example 2: comparing arrays of objects
This is the case array_diff() cannot handle. Here we compare two arrays of Product objects by their id, returning the products that are not in the second list:
<?php
class Product {
public function __construct(public int $id, public string $name) {}
}
$catalog = [
new Product(1, 'Keyboard'),
new Product(2, 'Mouse'),
new Product(3, 'Monitor'),
];
$discontinued = [
new Product(2, 'Mouse'),
];
$available = array_udiff(
$catalog,
$discontinued,
fn(Product $a, Product $b) => $a->id <=> $b->id
);
foreach ($available as $product) {
echo $product->id . ': ' . $product->name . PHP_EOL;
}
?>This prints the products whose id is not present in $discontinued:
1: Keyboard
3: MonitorBecause the callback compares only the id, the differing name values are irrelevant — the comparison logic is entirely yours to define.
Things to keep in mind
- The callback is always the last argument, no matter how many arrays you pass.
array_udiff()compares values. To compare by both keys and values, usearray_udiff_assoc(); to compare keys with a callback too, usearray_udiff_uassoc().- Return a proper three-way result (negative /
0/ positive), not just0or1. PHP relies on the ordering to compare efficiently, and a sloppy callback can produce wrong results. - The result preserves the keys and order of
$array1. Callarray_values()if you want a re-indexed array. - Only values from the first array can appear in the output — values unique to the later arrays are never returned.
Related functions
array_diff()— the same idea with plain string comparison.array_udiff_assoc()— value callback plus key comparison.array_uintersect()— the intersection equivalent (values found in all arrays).- PHP Arrays and PHP Functions for the fundamentals.