Vorsicht bei der Verwendung von isset() mit Arrays

Manchmal sucht man Fehler, die man wieder und wieder überliest, weil man die falschen Annahmen getroffen hat und der Code oberflächlich richtig aussieht. Erfahrungsgemäß gibt es dann ein paar “übliche Verdächtige”, die man sich genauer anschaut. Zuweisungen im if-Statement, Vergleiche ohne Typprüfung, empty() und isset() sind dabei immer heiße Kandidaten.

Wenn man die Handbuch-Seite zu isset() durchliest, klingt es, als wäre es problemlos möglich auch die Existenz von Array-Keys zu prüfen. Sogar ein schönes Beispiel gibt es dazu:

<?php
$a = array (
    'test' => 1,
    'hello' => NULL,
    'pie' => array('a' => 'apple'),
);
 
var_dump(isset($a['test']));            // TRUE
var_dump(isset($a['foo']));             // FALSE
var_dump(isset($a['hello']));           // FALSE
 
// The key 'hello' equals NULL so is considered unset
// If you want to check for NULL key values then try: 
var_dump(array_key_exists('hello', $a)); // TRUE
 
// Checking deeper array values
var_dump(isset($a['pie']['a']));        // TRUE
var_dump(isset($a['pie']['b']));        // FALSE
var_dump(isset($a['cake']['a']['b']));  // FALSE

Doch ganz so einfach ist es leider nicht. Interessant ist hier vor allem die letzte Zeile. Erst auf den zweiten Blick fällt auf, dass als erster Schlüssel “cake” statt “pie” verwendet wird. Und das ist der einzige Grund dafür, dass FALSE zurückgegeben wird. Ändert man nämlich den ersten Schlüssel auf “pie”, wird TRUE zurückgegeben, auch wenn der dritte Key nicht existiert:

<?php
$a = array(
    'test' => 1,
    'hello' => NULL,
    'pie' => array('a' => 'apple'),
);
 
var_dump(isset($a['pie']['a']['b']));  // TRUE

Das Problem und die Lösung wird auch in einem Kommentar von 2004 angesprochen. Die Prüfung mit isset() reicht nicht aus. Zusätzlich muss auf den vorletzen Key mit is_array() geprüft werden:

<?php
$a = array (
    'test' => 1,
    'hello' => NULL,
    'pie' => array('a' => 'apple'),
);
 
var_dump(isset($a['pie']['a']['b']) && is_array($a['pie']['a']));  // FALSE

Wichtig ist hier auch, dass man zuerst das isset() und danach das is_array() schreibt, sonst bekommt man einen Undefined-index-Fehler, wenn der Schlüssel komplett nicht vorhanden ist. Ein alleinstehendes isset() in Verbindung mit einem Array sollte einen also immer misstrauisch machen. Je nach Fall sollte ein is_array() ergänzt oder ein array_key_exists() bevorzugt werden.