Arrays7 min readExamples run on PHP 8.5.10

array_keys()

Learn how array_keys() returns all keys of a PHP array or only the keys whose values match a filter, with loose and strict comparison examples.

Signature

array_keys(array $array): array
array_keys(array $array, mixed $filter_value, bool $strict = false): array

Purpose

array_keys() pulls the keys out of an array and gives them back as a new, zero-indexed list. It has two modes. Called with only an array, it returns every key. Called with a search value, it returns only the keys whose elements match that value. The second mode is handy when the same value can appear under several keys and you want all of those positions, not just the first one that array_search() would find.

Signature

Parameters and defaults

  • $array: the array whose keys you want. Both integer and string keys are returned.
  • $filter_value: optional. When you supply it, only keys whose value matches are returned. Passing null explicitly still counts as supplying a filter, so it searches for null-like values rather than returning every key.
  • $strict: optional, default false. With false, values are compared loosely, like ==. With true, comparison uses ===, so type and value must both match. It only has an effect when a filter value is given.

Return value and failure cases

The function always returns an array. The result is a list with keys 0, 1, 2, ... and the original keys as its values, in the original array order. If nothing matches, or the input is empty, you get an empty array []. It does not return false for a missing match. Passing something that is not an array raises a TypeError.

Example 1: all keys, with key normalization

PHP normalizes array keys when the array is built. A string such as "10" that is a canonical decimal integer becomes the integer 10, while "01" stays a string. array_keys() reports the keys as they are actually stored.

Example
<?php
$data = ["id" => 7, "10" => "ten", "01" => "zero-one", 3 => "x"];
echo json_encode(array_keys($data), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
["id",10,"01",3]

Example 2: filtering by value

When several entries share a value, the filter form returns every key that holds it. Searching for a value that does not occur gives an empty array.

Example
<?php
$tasks = ["write" => "done", "test" => "open", "ship" => "done"];
echo json_encode(array_keys($tasks, "done")), "\n";
echo json_encode(array_keys($tasks, "blocked")), "\n";
Output
["write","ship"]
[]

Example 3: loose versus strict matching

Loose comparison can match more than you expect. In PHP 8, 0 equals "0", false and null loosely, but not the non-numeric string "a". Strict mode narrows the result to an identical value and type. The last line shows that an explicit null filter is a real search.

Example
<?php
$values = [0, "0", false, null, "a"];
echo json_encode(array_keys($values, 0)), "\n";
echo json_encode(array_keys($values, 0, true)), "\n";
echo json_encode(array_keys($values, null)), "\n";
Output
[0,1,2,3]
[0]
[0,2,3]

Edge cases

  • Empty array: array_keys([]) returns [].
  • Order is preserved: keys come back in the order the elements are stored, not sorted.
  • Nested arrays: only the top-level keys are returned. The function does not descend into child arrays.
  • Result is a list: the returned array is renumbered from zero, so its own keys are not the original keys. Use array_keys() output as values, not as an index.
  • Array values as filters: you can pass an array as $filter_value. Loose comparison then compares arrays element by element, and strict comparison requires identical key/value pairs in the same order and of the same types.

Common mistakes

  1. Forgetting loose comparison. With array_keys($list, 0) on mixed data, entries such as false, null and "0" also match. Pass true for $strict when types matter.
  2. Expecting a single key. The function returns a list even when only one key matches. Take [0] of the result only after checking that it is not empty.
  3. Using it to test for a key. To check whether a key exists, use array_key_exists() or isset(). Building a list of every key just for that test is wasteful.
  4. Confusing it with array_values(). array_keys() returns the keys, array_values() returns the values.
  5. Assuming "01" becomes an integer. Only canonical decimal integer strings are converted. Leading zeros keep the key a string.
  6. Passing null and expecting all keys. An explicit null is a search value. Omit the argument to get all keys.
  • array_values() returns the values with keys renumbered.
  • array_search() returns only the first matching key.
  • array_key_exists() checks whether a specific key is present.
  • array_combine() builds an array from a list of keys and a list of values.
  • array_flip() swaps keys and values.

Recap

array_keys($array) lists all keys. Add a $filter_value to get only the keys whose values match, and set $strict to true when you need identical types. The result is always a zero-indexed array, empty when nothing matches.

Tested examples

All keys, including normalized integer keys
<?php
$data = ["id" => 7, "10" => "ten", "01" => "zero-one", 3 => "x"];
echo json_encode(array_keys($data), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
["id",10,"01",3]
Filtering keys by value
<?php
$tasks = ["write" => "done", "test" => "open", "ship" => "done"];
echo json_encode(array_keys($tasks, "done")), "\n";
echo json_encode(array_keys($tasks, "blocked")), "\n";
Output
["write","ship"]
[]
Loose versus strict matching
<?php
$values = [0, "0", false, null, "a"];
echo json_encode(array_keys($values, 0)), "\n";
echo json_encode(array_keys($values, 0, true)), "\n";
echo json_encode(array_keys($values, null)), "\n";
Output
[0,1,2,3]
[0]
[0,2,3]