Signature
key(array|object $array): int|string|nullPurpose
Every PHP array carries an internal pointer that marks one element as the "current" one. key() reports the key of that element. It only reads the pointer. It never moves it, so calling it ten times in a row gives the same answer ten times.
The pointer is controlled by a family of functions: current() returns the value, next() and prev() step the pointer, reset() sends it to the first element, and end() sends it to the last. key() is the companion that tells you where you are, in terms of keys rather than values.
Signature
Parameters and defaults
$arrayis the array whose pointer is inspected. There are no other parameters and no default values.- The signature also lists
object, but callingkey()on an object has been deprecated since PHP 8.1. If you need the same behaviour for an object, convert it first withget_mangled_object_vars(), or use an iterator class such asArrayIteratorthat has its ownkey()method. For ordinary work, pass arrays only.
Return value and failure cases
- It returns an
intorstring: the key of the element the pointer currently references. - It returns
nullif the pointer has moved beyond the last element, or if the array is empty. - Because an array key can never be
null, anullresult is unambiguous: it always means "no current element".
A fresh array has its pointer on the first element, so key() on a new array gives its first key without any setup.
Example 1: walking the pointer
This example shows the key at the start, after one step, and after stepping past the end.
$stack = ['a' => 10, 'b' => 20, 'c' => 30];
echo json_encode(key($stack)), "\n";
next($stack);
echo json_encode(key($stack)), "\n";
next($stack);
next($stack);
echo json_encode(key($stack)), "\n";"a" "b" null
The first call reports "a", the second "b", and after moving past "c" the result is null.
Example 2: key() does not advance
Integer keys continue from the highest previous integer key, so [5 => 'x', 'y', 'z'] has keys 5, 6 and 7. Repeated calls do not change the pointer; only next() does.
$list = [5 => 'x', 'y', 'z'];
echo key($list), "\n";
echo key($list), "\n";
echo current($list), "\n";
next($list);
echo key($list), ':', current($list), "\n";5 5 x 6:y
Example 3: collecting matching keys safely
A common use is scanning an array and recording the keys of matching values. The loop condition tests key() against null instead of testing the value, so falsy values such as 0 do not end the loop early.
$flags = ['a' => 'apple', 'b' => 0, 'c' => 'apple', 'd' => 'pear'];
$found = [];
while (($k = key($flags)) !== null) {
if (current($flags) === 'apple') {
$found[] = $k;
}
next($flags);
}
echo json_encode($found), "\n";["a","c"]
The result is ["a","c"]. Had the loop used while ($value = current($flags)), it would have stopped at the 0 under key b.
Edge cases
- Empty arrays:
key([])returnsnull. - Pointer past the end: once
next()has moved beyond the last element,key()staysnulluntil you callreset()orend(). - Numeric string keys: a key such as
"7"is stored as the integer7, sokey()returns anintfor it. - foreach: a
foreachloop does not use or move the internal pointer in modern PHP, so it will not change whatkey()returns, andkey()will not tell you the currentforeachposition. - Copies: the pointer is part of the array value. Work with the variable you actually moved, not a different copy of it.
Common mistakes
- Expecting key() to advance. It never does. Pair it with
next()explicitly. - Looping on the value.
while ($v = current($a))stops at the first falsy value. Testkey($a) !== nullinstead. - Using a loose null check. Keys such as
0and""are valid, and0is falsy. Always compare with!== null. - Forgetting reset(). If earlier code moved the pointer,
key()will not give the first key. Callreset()first when you need a known starting point. - Passing objects. This is deprecated since PHP 8.1; use arrays or iterator classes.
- Reaching for key() when you only want the first key.
array_key_first()is clearer and does not depend on pointer state.
Related functions
current()returns the value at the pointer.next()advances the pointer andprev()moves it back.reset()andend()jump to the first and last elements.array_key_first()andarray_key_last()fetch boundary keys without touching the pointer.foreachiterates keys and values without manual pointer handling.
Recap
key() reads the key at an array's internal pointer and returns int|string|null. It does not move the pointer, and it returns null for an empty array or when the pointer is past the end. Loop with key($array) !== null, step with next(), and avoid objects, which are deprecated since PHP 8.1.
Tested examples
$stack = ['a' => 10, 'b' => 20, 'c' => 30];
echo json_encode(key($stack)), "\n";
next($stack);
echo json_encode(key($stack)), "\n";
next($stack);
next($stack);
echo json_encode(key($stack)), "\n";"a" "b" null
$list = [5 => 'x', 'y', 'z'];
echo key($list), "\n";
echo key($list), "\n";
echo current($list), "\n";
next($list);
echo key($list), ':', current($list), "\n";5 5 x 6:y
$flags = ['a' => 'apple', 'b' => 0, 'c' => 'apple', 'd' => 'pear'];
$found = [];
while (($k = key($flags)) !== null) {
if (current($flags) === 'apple') {
$found[] = $k;
}
next($flags);
}
echo json_encode($found), "\n";["a","c"]