Arrays7 min readExamples run on PHP 8.5.10

array_diff_ukey()

Learn how PHP 8.4 array_diff_ukey() compares array keys with your own callback, which entries it keeps, and which mistakes to avoid.

Signature

array_diff_ukey(array $array, array ...$arrays, callable $key_compare_func): array
Available since PHP 5.1.07.48.08.18.28.38.48.5All versions →

Purpose

array_diff_ukey() returns the entries of the first array whose keys do not appear in any of the other arrays. Unlike array_diff_key(), which uses PHP's built-in key comparison, this function asks your callback whether two keys count as equal. That makes it useful when keys should match case-insensitively, after trimming, or by some other custom rule.

Values are never compared. Only keys matter, and the entries that survive keep their original keys and their original order.

Signature

Parameters

  • $array: the array to compare from. Entries are taken from this array only.
  • ...$arrays: one or more arrays whose keys are compared against. A key from $array is removed if the callback reports a match in any of them.
  • $key_compare_func: a callable that receives two keys and returns an integer. It must return a value below zero, zero, or above zero when the first key is considered smaller than, equal to, or greater than the second. Zero means "these keys are the same". The callback must be the last argument. It has no default value.

Return value and failure cases

The function returns an array containing every entry from $array that is not matched in the other arrays. If nothing is left, you get an empty array. Passing something that is not an array, or a callback that is not callable, raises a TypeError. Exceptions thrown inside your callback propagate to the caller.

Example 1: a basic key difference

Here the callback uses the spaceship operator, which behaves like plain string comparison. Entries whose keys exist in $sold are dropped.

Example
<?php
$stock = ['blue' => 1, 'red' => 2, 'green' => 3, 'purple' => 4];
$sold = ['green' => 5, 'blue' => 6, 'yellow' => 7];
$left = array_diff_ukey($stock, $sold, fn(string $a, string $b): int => $a <=> $b);
echo json_encode($left, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"red":2,"purple":4}

Only red and purple have no counterpart, so only they remain, with their values untouched.

Example 2: case-insensitive keys

Built-in functions can serve as the callback. strcasecmp returns zero when two strings differ only by ASCII case, so Host and host are treated as the same key.

Example
<?php
$defaults = ['Host' => 'localhost', 'PORT' => 3306, 'Charset' => 'utf8'];
$provided = ['host' => 'db.test', 'port' => 5432];
$missing = array_diff_ukey($defaults, $provided, 'strcasecmp');
echo json_encode($missing, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"Charset":"utf8"}

The result contains only the default that the caller did not supply.

Example 3: several comparison arrays

When you pass more than one array to compare against, a key is removed if it matches in any of them.

Example
<?php
$a = ['a1' => 1, 'b2' => 2, 'c3' => 3, 'd4' => 4];
$b = ['A1' => 0];
$c = ['D4' => 0];
$compare = fn(string $x, string $y): int => strcasecmp($x, $y);
echo json_encode(array_diff_ukey($a, $b, $c, $compare), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"b2":2,"c3":3}

The keys a1 and d4 are removed through different comparison arrays, leaving b2 and c3.

Edge cases

  • Only keys count. Two entries with identical values but different keys are different entries. Use array_udiff() if you need to compare values.
  • Integer-like keys. PHP converts keys such as "5" to the integer 5. Your callback may receive integers, so avoid assuming strings, or write a callback that accepts int|string.
  • One dimension only. Nested arrays are not compared recursively. To check a deeper level, call the function on the nested arrays yourself.
  • Float results are truncated. The callback's return value is cast to an integer. A comparison returning 0.5 becomes 0 and is treated as equal.
  • The callback should be a consistent ordering. It should give the same answer for the same pair and behave like a real comparison, not like a loose yes/no check.

Common mistakes

  1. Returning a boolean. A callback such as fn($a, $b) => $a == $b returns true for equal keys, which becomes 1, meaning "greater than". Equal keys must return 0. Use <=> or strcmp-style functions.
  2. Putting the callback first. The callable is always the final argument. Placing it elsewhere causes a TypeError.
  3. Expecting values to matter. The 0 values in Example 3 play no role in the result.
  4. Expecting reindexing. Keys are preserved, so a numerically indexed result can have gaps. Wrap the result in array_values() when you need a list.
  5. Using the wrong function for simple cases. If strict built-in key equality is enough, array_diff_key() is shorter and faster.
  • array_diff_key(): the same key-only difference using built-in comparison.
  • array_diff_uassoc(): compares values with the built-in rule and keys with your callback.
  • array_udiff(): compares values with a callback.
  • array_udiff_uassoc(): uses callbacks for both values and keys.
  • array_intersect_ukey(): keeps entries whose keys do match under a callback.
  • array_diff(): the basic value-based difference.

Recap

array_diff_ukey() keeps the entries of the first array whose keys are not matched, under your callback, by any key in the other arrays. The callback must return an integer where 0 means equal, it must come last, and the original keys and order are preserved. Reach for it when plain key equality is too strict, such as with case-insensitive configuration names.

Tested examples

Basic key difference with a spaceship callback
<?php
$stock = ['blue' => 1, 'red' => 2, 'green' => 3, 'purple' => 4];
$sold = ['green' => 5, 'blue' => 6, 'yellow' => 7];
$left = array_diff_ukey($stock, $sold, fn(string $a, string $b): int => $a <=> $b);
echo json_encode($left, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"red":2,"purple":4}
Case-insensitive key comparison with strcasecmp
<?php
$defaults = ['Host' => 'localhost', 'PORT' => 3306, 'Charset' => 'utf8'];
$provided = ['host' => 'db.test', 'port' => 5432];
$missing = array_diff_ukey($defaults, $provided, 'strcasecmp');
echo json_encode($missing, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"Charset":"utf8"}
Comparing against several arrays
<?php
$a = ['a1' => 1, 'b2' => 2, 'c3' => 3, 'd4' => 4];
$b = ['A1' => 0];
$c = ['D4' => 0];
$compare = fn(string $x, string $y): int => strcasecmp($x, $y);
echo json_encode(array_diff_ukey($a, $b, $c, $compare), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"b2":2,"c3":3}