Getting the first key meant reset() then key(), which moves the internal pointer — so a read had a side effect on an array the caller may still be iterating.
// before
reset($rows);
$first = key($rows);
// 7.3
$first = array_key_first($rows);
$last = array_key_last($rows);
if ($first === null) {
// empty. keys are int|string, so null is unambiguous.
}
Neither touches the pointer, which is the real improvement — the old idiom was a mutation dressed as a read, and it broke any caller in the middle of a foreach over a reference. Both return null for an empty array, and because keys can only be integers or strings that is not ambiguous. The equivalent for values is still reset(), which is an asymmetry nobody has explained.