Just Lucky Really
Just Lucky Really

Reputation: 1401

Php array offset passes 'isset', even though it's not set

The easiest way for me to explain this is to show an example ... Here's a replication of the problem code:

<?php
    $test=array();
    $test['one']='hello';
    if(isset($test['one']['two'][0])) {
        echo 'Apparently it is set ...';
        echo $test['one']['two'][0];
   }
?>

This returns as:

Apparently it is set ...

Warning: Illegal string offset 'two' in C:\test.php on line 6

h

Is this because there are mixed key types? It's just a little anomaly I came across and was wondering if someone could shed some light on it ...

Upvotes: 3

Views: 167

Answers (3)

Ja͢ck
Ja͢ck

Reputation: 173642

The reason is that, when you dereference a string, it will return a string comprising a single character (assuming the index doesn't exceed the length); the resulting string can be dereferenced again (starting from 5.4 onwards).

For example - link:

$s = 'hello';
$s[0];    // "h"
$s[0][0]; // "h"
// etc. etc.

Illegal indices such as 'two' will cause a notice but it's treated as index 0, except when used inside isset().

Another example:

$s[0][1];    // ""
$s[0][1][0]; // notice: uninitialised string offset: 0

If you don't know beforehand whether a string or array is passed and this is important to you, additional type checks need to take place in between each path.

Upvotes: 4

Manmaru
Manmaru

Reputation: 578

isset returns odd and unexpected results when you pass it a string instead of an array.

It is good practice to pair an an is_array check with an isset check.

Upvotes: -1

scrowler
scrowler

Reputation: 24405

You should check your all your array keys exist before you try and use them, i.e. all the way up the chain. isset() accepts multiple parameters so you don't need to keep rewriting it and can keep DRY principles going a little more:

$test = array();
$test['one'] = 'hello';
if (isset($test['one'], $test['one']['two'], $test['one']['two'][0])) {
    echo 'Apparently it is set ...';
    echo $test['one']['two'][0];
}

Upvotes: 0

Related Questions