PHP: Solve undefined key / offset / property warnings. Multi-level nested keys

By | February 15, 2021
Bismillahi-r-Rahmani-r-Rahim (In the name of Allah, the most Compassionate, the most Merciful)

Sometimes we may want to return null or empty string for non-existing multi-level/nested keys or properties in PHP instead of warnings. Also it would be convenient to use bracket ([]) and arrow (->) operators for array keys / object properties interchangeably.

First let’s initialize some variables in below PHP code block:

class Foo {
    public $prop1 = 'prop1_val';
    public $prop2 = ['key' => 'val'];
    public $prop3 = [];
}
$cls = new Foo();
$cls->prop3 = ['cls' => new Foo()];
$arr1 = ['key1' => 'val1'];

Now let’s execute the following:

echo $arr1['key1'].'<br>';
echo $cls->prop1.'<br>';
echo $cls->prop2['key'].'<br>';
echo $cls->prop3['cls']->prop2['key'].'<br>';

The output of the above code will be (no errors or warnings, all clean):

val1
prop1_val
val
val
But what happens when we execute the following code:
echo $arr1['key2'].'<br>'; // non existent array key
echo $cls->prop4.'<br>'; // non existent object property
echo $cls['prop3']['cls']->prop2['key'].'<br>'; // call object property using [] operator

The output will be:

Warning: Undefined array key "key2" in...
Warning: Undefined property: Foo::$prop4 in...
Fatal error: Uncaught Error: Cannot use object of type Foo as array in...

Solution 1 – isset function

We can use PHP’s isset($var) function to check if variable is set before using it. This will solve undefined key and undefined property issues.

echo (isset($arr1['key2']) ? $arr1['key2'] : 'def_val').'<br>';
echo (isset($arr1['k1']['k2']) ? $arr1['k1']['k2'] : 'def_val').'<br>'; // nesting array keys also works
echo (isset($cls->prop4) ? $cls->prop4 : 'def_val').'<br>';
echo isset($cls['prop3']['cls']->prop2['key']) ? $cls['prop3']['cls']->prop2['key'] : 'def_val';

Output:

def_val
def_val
def_val
Fatal error: Uncaught Error: Cannot use object of type Foo as array in...

This solution fixes only undefined key/property issue, but Cannot use object of type Foo as array error still remains. Also we need to call the same key twice which may be problematic for very large arrays.


Solution 2 – property_exists / array_key_exists functions

Similar to Solution1 we can use PHP’s property_exists($cls, $prop) and array_key_exists($key, $arr) functions that would fix undefined key/property issue perfectly:

echo (array_key_exists('key2', $arr1) ? $arr1['key2'] : 'def_val').'<br>';
echo (array_key_exists('k1', $arr1) && array_key_exists('k2', $arr1['k1']) ? $arr1['k1']['k2'] : 'def_val').'<br>';
echo (property_exists($cls, 'prop4') ? $cls->prop4 : 'def_val').'<br>';
// $cls['prop3']['cls']->prop2['key'] - complicated mixture of the above functions, too lazy to code...

The output will be similar to Solution1. But syntactically speaking this is not the best solution.


Solution 3 – ?? coalesce operator (>=PHP 7)

echo ($arr1['key2'] ?? 'def_val').'<br>';
echo ($arr1['k1']['k2'] ?? 'def_val').'<br>';
echo ($cls->prop4 ?? 'def_val').'<br>';
echo ($cls['prop3']['cls']->prop2['key']);

Output is the same and Cannot use object of type Foo as array error still remains. But this solution seems better than others.

The good and detailed discussion about these 3 solutions can be found in https://stackoverflow.com/questions/700227/whats-quicker-and-better-to-determine-if-an-array-key-exists-in-php.


Solution 4 – disable warnings

$old_val = ini_get('display_errors');
ini_set('display_errors', 'off');
echo $arr1['key2'];
ini_set('display_errors', $old_val);

Solution 5 – custom function

Finally, we can develop our own custom function, that will solve all of the problems. It is also possible to mix array keys and object properties in key chain list.