Arrays7 min readExamples run on PHP 8.5.10

array_filter()

Learn how array_filter() keeps only the array elements you want, how keys are preserved, how the mode flags work, and which mistakes to avoid.

Signature

array_filter(array $array, ?callable $callback = null, int $mode = 0): array
Available since PHP 4.0.67.48.08.18.28.38.48.5All versions →

Purpose

array_filter() walks over an array and builds a new array that contains only the elements you want to keep. You decide what to keep with a callback that returns a truthy or falsy result. If you omit the callback, PHP removes every element that counts as empty. The original array is never modified; you always get a fresh array back.

Signature

Parameters and defaults

  • $array: the array to iterate over.
  • $callback: a function called for each element. If it returns a truthy value, the element is copied into the result. The default is null, which means no callback is used and each value is checked the way empty() would check it.
  • $mode: controls what the callback receives. The default 0 passes only the value. ARRAY_FILTER_USE_KEY passes only the key. ARRAY_FILTER_USE_BOTH passes the value first and the key second. When $callback is null, the mode is ignored.

Return value and failure cases

The function returns an array, possibly an empty one when nothing passes the test. Keys are preserved, so a filtered list can contain gaps in its numeric keys. Call array_values() on the result when you need a tidy, zero-based list.

Passing something that is not callable as $callback raises a TypeError. Since PHP 8.0.0 the callback is nullable, and a callback that expects a parameter by reference triggers an E_WARNING. The manual also warns that changing the array from inside the callback, such as adding or unsetting elements, gives undefined behavior, so keep callbacks free of side effects.

Example 1: filtering by value

The callback receives each value in turn. Notice that the surviving elements keep their original keys, and that array_values() renumbers them.

Example
<?php
$numbers = [1, 2, 3, 4, 5, 6];
$even = array_filter($numbers, fn(int $n): bool => $n % 2 === 0);
echo json_encode($even), "\n";
echo json_encode(array_values($even)), "\n";
Output
{"1":2,"3":4,"5":6}
[2,4,6]

Because the keys 1, 3 and 5 survive, JSON encodes the first result as an object rather than a list.

Example 2: filtering without a callback

Without a callback, every falsy value is removed. This includes false, null, 0, the empty string, the string '0' and an empty array. Strings such as '0.0' are not falsy and stay.

Example
<?php
$entry = ['foo', false, -1, null, '', '0', 0, [], '0.0'];
echo json_encode(array_filter($entry), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"0":"foo","2":-1,"8":"0.0"}

This is handy for cleaning up form-like input, but be careful: a legitimate 0 is removed along with the junk.

Example 3: using keys with the mode flag

With ARRAY_FILTER_USE_KEY the callback sees only the key. With ARRAY_FILTER_USE_BOTH it sees the value and then the key, so the parameter order is $value, $key.

Example
<?php
$prices = ['apple' => 120, 'banana' => 80, 'cherry' => 300, 'avocado' => 150];
$byKey = array_filter($prices, fn(string $key): bool => str_starts_with($key, 'a'), ARRAY_FILTER_USE_KEY);
$both = array_filter($prices, fn(int $price, string $key): bool => $price >= 100 && $key !== 'apple', ARRAY_FILTER_USE_BOTH);
echo json_encode($byKey), "\n";
echo json_encode($both), "\n";
Output
{"apple":120,"avocado":150}
{"cherry":300,"avocado":150}

Edge cases

  • An empty input array returns an empty array.
  • If no element passes, the result is an empty array, not false.
  • The callback result is judged for truthiness, so returning 1, "yes" or true all keep the element. Returning 0 or null drops it. A bitwise expression such as $n & 1 works, but an explicit boolean is clearer.
  • Numeric-looking string keys are stored as integers in PHP arrays. With ARRAY_FILTER_USE_KEY, a callback that declares a string key type may behave unexpectedly in strict-types code, so use no type or a union such as int|string when keys can be mixed.
  • The relative order of the surviving elements stays the same.

Common mistakes

  1. Expecting a reindexed list. After filtering, indexes may have gaps. Wrap the call in array_values() before encoding as a JSON list or accessing [0].
  2. Using no callback on data where zero is valid. Quantities, scores and prices of 0 vanish. Supply a callback such as fn($v) => $v !== null to remove only what you intend.
  3. Mixing up the parameter order in ARRAY_FILTER_USE_BOTH. The value comes first, the key second.
  4. Forgetting the mode flag. Without it, a callback written for keys receives values instead.
  5. Modifying the array inside the callback. The behavior is undefined; compute the changes separately.
  6. Using it to transform values. array_filter() only selects; it never changes the elements. Use array_map() for transformation.
  • array_values() renumbers keys after filtering.
  • array_map() transforms every element.
  • array_reduce() collapses an array to a single value.
  • array_find() returns the first element satisfying a callback.
  • array_any() tells you whether at least one element satisfies a callback.
  • array_intersect() keeps values that also appear in other arrays.

Recap

array_filter() returns a new array holding only elements that pass your test. Keys are preserved, so reindex with array_values() when order matters more than keys. With no callback it removes all falsy values, and the mode argument lets the callback inspect keys, or both values and keys.

Tested examples

Filter values and reindex the result
<?php
$numbers = [1, 2, 3, 4, 5, 6];
$even = array_filter($numbers, fn(int $n): bool => $n % 2 === 0);
echo json_encode($even), "\n";
echo json_encode(array_values($even)), "\n";
Output
{"1":2,"3":4,"5":6}
[2,4,6]
Remove falsy values without a callback
<?php
$entry = ['foo', false, -1, null, '', '0', 0, [], '0.0'];
echo json_encode(array_filter($entry), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"0":"foo","2":-1,"8":"0.0"}
Filter by key and by value with mode flags
<?php
$prices = ['apple' => 120, 'banana' => 80, 'cherry' => 300, 'avocado' => 150];
$byKey = array_filter($prices, fn(string $key): bool => str_starts_with($key, 'a'), ARRAY_FILTER_USE_KEY);
$both = array_filter($prices, fn(int $price, string $key): bool => $price >= 100 && $key !== 'apple', ARRAY_FILTER_USE_BOTH);
echo json_encode($byKey), "\n";
echo json_encode($both), "\n";
Output
{"apple":120,"avocado":150}
{"cherry":300,"avocado":150}