Signature
array_diff(array $array, array ...$arrays): arrayPurpose
array_diff() answers the question: which values in my first array do not appear anywhere in the other arrays? It is handy for removing banned words, excluding IDs that are already taken, or finding items that were dropped between two lists. Only the values are compared. Keys play no part in deciding what stays.
Signature
Parameters and defaults
$array: the array you want to filter. Every entry from it that has no match elsewhere is kept....$arrays: zero or more arrays to compare against. An entry of$arrayis dropped if it matches a value in any of them.
There are no default values. The function can be called with a single argument, in which case nothing is removed and you get the same entries back.
Return value and failure cases
The function returns an array containing the entries of $array that are not present in any of the other arrays. Keys from $array are preserved, so the result often has gaps in its numeric keys. Wrap the call in array_values() when you need a clean list.
Passing something that is not an array raises a TypeError. Two values count as equal only when their string forms are identical, that is (string) $a === (string) $b. A nested array inside either side cannot be converted to a string, so PHP emits an "Array to string conversion" warning. An object is usable only if it can be cast to a string, for example through __toString().
Example 1: keys are preserved
Duplicates in the first array are treated identically: every "red" is removed because "red" exists in the second array. The "green" under key a is removed too, even though the second array stores it under a different key.
$all = ["a" => "green", "red", "blue", "red"];
$other = ["b" => "green", "yellow", "red"];
echo json_encode(array_diff($all, $other), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"1":"blue"}
The surviving entry is "blue" and it still has key 1, so the JSON output is an object rather than a list.
Example 2: several arrays and reindexing
You can pass any number of comparison arrays. Because comparison is by string value, the string "5" matches the integer 5.
$ids = [1, 2, 3, 4, 5, 6];
$sold = [2, 4];
$reserved = ["5"];
$available = array_values(array_diff($ids, $sold, $reserved));
echo json_encode($available), "\n";[1,3,6]
Without array_values() the result would keep keys 0, 2 and 5. After reindexing you get a plain list.
Example 3: string comparison surprises
The comparison does not care about the original type. The values "", null and false all become the empty string, and 1.0 becomes "1".
$left = [0, "0", "", null, false, "a", 1.0];
$right = ["", "1"];
echo json_encode(array_diff($left, $right), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"0":0,"1":"0","5":"a"}
The empty string, null, false and 1.0 are all removed. The two zeros and "a" remain, with their original keys 0, 1 and 5.
Edge cases
- If the first array is empty, the result is empty.
- If the comparison arrays are empty, or you pass none, every entry of the first array is kept.
- Only the first dimension is checked. To compare deeper levels, call
array_diff()on the inner arrays yourself, for instance on$a[0]and$b[0]. - The function is not symmetric.
array_diff($a, $b)andarray_diff($b, $a)usually give different results. If you need both directions, call it twice.
Common mistakes
- Expecting a list back. Since keys are preserved, code that later uses
$result[0]may fail. Reindex witharray_values()when order matters more than keys. - Assuming type-aware comparison.
0and"0"are the same here, as arefalseand"". If your data mixes types in a meaningful way, normalize it first or use a callback-based variant. - Comparing arrays of arrays. Rows like
["id" => 1]cannot be converted to strings, so they trigger warnings and do not compare meaningfully. Extract a column, such as IDs, and diff that instead. - Expecting key checks.
array_diff()ignores keys entirely. When both the key and the value must match, usearray_diff_assoc(). - Mixing up the argument order. The first array is the one being filtered. The others are only a list of things to remove.
Related functions
array_diff_assoc()compares both key and value.array_udiff()lets you supply your own comparison callback.array_intersect()keeps values that are present in all arrays, the opposite idea.array_intersect_assoc()is the intersection with an added key check.array_values()reindexes the result into a list.
Recap
array_diff() returns the entries of the first array whose string value does not occur in any other supplied array. It keeps original keys, treats values by their string representation, only inspects one dimension, and is not symmetric. Reindex when you need a list, and reach for a different diff function when keys or custom comparison rules matter.
Tested examples
$all = ["a" => "green", "red", "blue", "red"];
$other = ["b" => "green", "yellow", "red"];
echo json_encode(array_diff($all, $other), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
{"1":"blue"}
$ids = [1, 2, 3, 4, 5, 6];
$sold = [2, 4];
$reserved = ["5"];
$available = array_values(array_diff($ids, $sold, $reserved));
echo json_encode($available), "\n";
[1,3,6]
$left = [0, "0", "", null, false, "a", 1.0];
$right = ["", "1"];
echo json_encode(array_diff($left, $right), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
{"0":0,"1":"0","5":"a"}