Arrays7 min readExamples run on PHP 8.5.10

array_uintersect()

Learn how PHP's array_uintersect() keeps values found in every array, using your own comparison callback, with examples, edge cases and common mistakes.

Signature

array_uintersect(array $array, array ...$arrays, callable $value_compare_func): array

Purpose

array_uintersect() computes the intersection of two or more arrays, but lets you decide what "the same value" means. Plain array_intersect() compares values as strings. With array_uintersect() you supply a callback, so you can compare case-insensitively, match records by an ID, compare by length, and so on.

The result contains the entries of the first array whose values are present in every other array. Keys of the first array are preserved.

Signature

The callback is the last argument, after all the arrays. Its shape is:

function callback(mixed $a, mixed $b): int

Parameters

  • $array: the first array. Its values and keys are what can appear in the result.
  • ...$arrays: one or more further arrays to compare against.
  • $value_compare_func: a callable that returns an integer less than, equal to, or greater than zero when the first argument is considered less than, equal to, or greater than the second. There is no default; the callback is required.

Return value and failure cases

The function returns an array containing all values of the first array that are present in all the other arrays. If nothing matches, the result is an empty array. Original keys from the first array are kept, so the result is often not a list.

Passing something that is not an array where an array is expected, or something that is not callable as the last argument, raises a TypeError.

Example 1: case-insensitive comparison

Using the built-in strcasecmp as the comparator treats green and GREEN as equal. Note that keys come from the first array, and only values are compared.

Example
<?php
$a = ["a" => "green", "b" => "brown", "c" => "blue", "red"];
$b = ["a" => "GREEN", "B" => "brown", "yellow", "red"];
echo json_encode(array_uintersect($a, $b, "strcasecmp"), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"a":"green","b":"brown","0":"red"}

Example 2: matching records by ID across three arrays

The callback can compare any part of a value. Here records are matched only by id, so differing names do not matter. The surviving entries come from the first array, with keys 0 and 2 preserved.

Example
<?php
$left = [["id" => 1, "name" => "Ana"], ["id" => 2, "name" => "Ben"], ["id" => 3, "name" => "Cy"]];
$right = [["id" => 3, "name" => "Cyrus"], ["id" => 1, "name" => "Anna"]];
$third = [["id" => 1], ["id" => 3], ["id" => 9]];
$result = array_uintersect($left, $right, $third, fn(array $x, array $y): int => $x["id"] <=> $y["id"]);
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"0":{"id":1,"name":"Ana"},"2":{"id":3,"name":"Cy"}}

Example 3: "equal" is whatever your callback says

The callback below compares string lengths. kiwi matches pear (both length 4) and fig matches dog (both length 3), while apple has no partner of length 5.

Example
<?php
$words = ["apple", "kiwi", "fig"];
$others = ["pear", "dog"];
$result = array_uintersect($words, $others, fn(string $x, string $y): int => strlen($x) <=> strlen($y));
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"1":"kiwi","2":"fig"}

Edge cases

  • Callback sees any pair. Each array is sorted internally with your callback before comparison, so the callback can receive any value from any array in any order. It must work for every combination, not just "a value from the first array versus a value from the second".
  • Consistent ordering matters. Because sorting is involved, the callback should behave like a real comparison: if a is less than b, then b must be greater than a. An inconsistent callback gives unpredictable results.
  • Mixed types. If arrays contain different kinds of values, such as strings, integers and nested arrays, the callback has to handle all of them safely.
  • No match. An empty array comes back when no value of the first array is present in all the others.
  • Keys are ignored for matching. Only values are compared; use array_uintersect_assoc() if keys should matter too.

Common mistakes

  1. Returning a boolean or float. The callback must return an integer. A float is cast to int, so values such as 0.99 and 0.1 both become 0 and are treated as equal. A boolean such as $a === $b cannot express "less than" versus "greater than". Use the spaceship operator <=> or strcmp-style functions.
  2. Putting the callback first. Unlike array_filter(), the callback goes last, after every array.
  3. Expecting a re-indexed list. The result keeps keys from the first array. Wrap the result in array_values() if you need sequential keys.
  4. Assuming the second array supplies the output. Output values always come from the first array, even when the other arrays hold "better" versions such as different spelling or extra fields.
  5. Writing a callback that only works on one shape. For example, reading $x["id"] fails if some array holds plain integers.
  • array_intersect(): intersection comparing values as strings.
  • array_intersect_assoc(): intersection that also checks keys.
  • array_uintersect_assoc(): callback for values, plus a strict key check.
  • array_uintersect_uassoc(): separate callbacks for values and keys.

Recap

array_uintersect() keeps the entries of the first array whose values match, according to your comparison callback, in every other array. The callback goes last and must return an integer, ideally via <=>. Keys of the first array are preserved, and the callback must handle any pair of values because the arrays are sorted internally.

Tested examples

Case-insensitive intersection with strcasecmp
<?php
$a = ["a" => "green", "b" => "brown", "c" => "blue", "red"];
$b = ["a" => "GREEN", "B" => "brown", "yellow", "red"];
echo json_encode(array_uintersect($a, $b, "strcasecmp"), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"a":"green","b":"brown","0":"red"}
Matching records by ID across three arrays
<?php
$left = [["id" => 1, "name" => "Ana"], ["id" => 2, "name" => "Ben"], ["id" => 3, "name" => "Cy"]];
$right = [["id" => 3, "name" => "Cyrus"], ["id" => 1, "name" => "Anna"]];
$third = [["id" => 1], ["id" => 3], ["id" => 9]];
$result = array_uintersect($left, $right, $third, fn(array $x, array $y): int => $x["id"] <=> $y["id"]);
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"0":{"id":1,"name":"Ana"},"2":{"id":3,"name":"Cy"}}
Comparing strings by length
<?php
$words = ["apple", "kiwi", "fig"];
$others = ["pear", "dog"];
$result = array_uintersect($words, $others, fn(string $x, string $y): int => strlen($x) <=> strlen($y));
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"1":"kiwi","2":"fig"}