33

Edit 2022: This appears to be fixed as of PHP 7.4 which emits a notice.


In PHP, I have error_reporting set to report everything including notices.

Why does the following not throw any notices, errors or anything else?

$myarray = null;
$myvalue = $myarray['banana'];

Troubleshooting steps:

$myarray = array();
$myvalue = $myarray['banana'];
// throws a notice, as expected ✔

$myarray = (array)null;
$myvalue = $myarray['banana'];
// throws a notice, as expected ✔

$myarray = null;
$myvalue = $myarray['banana'];
// no notice or warning thrown, $myvalue is now NULL. ✘ Why?

It's possible it's a bug in PHP, or I'm just not understanding something about how this works.

thomasrutter
  • 114,488
  • 30
  • 148
  • 167
  • 2
    PHP isn't really the most *logical* language when it comes to data types: http://me.veekun.com/blog/2012/04/09/php-a-fractal-of-bad-design/ – Blender Jun 12 '12 at 04:06
  • I agree with @Blender: it usually does what makes the most sense doing its best given what it knows. This is frequently quite convenient as far as not bothering anyone with trivial errors. – wallyk Jun 12 '12 at 04:22
  • 1
    Wow - I've worked with PHP for years and somehow never been bitten by this madness until today. A quick test reveals that this crazy design decision remains unchanged in PHP 7. :( – Mark Amery Sep 27 '15 at 12:25
  • You can even do this: ` – Rafał G. Oct 18 '16 at 17:03

4 Answers4

10

Usually, when you try to use a value of one type as if it were another type, either an error or warning gets thrown or "type juggling" takes place. For example, if you try to concatenate two numbers with ., they'll both get coerced to strings and concatenated.

However, as explained on the manual page about type juggling, this isn't the case when treating a non-array like an array:

The behaviour of an automatic conversion to array is currently undefined.

In practice, the behaviour that happens when this "undefined behaviour" is triggered by dereferencing a non-array is that null gets returned, as you've observed. This doesn't just affect nulls - you'll also get null if you try to dereference a number or a resource.

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
Narf
  • 14,600
  • 3
  • 37
  • 66
  • Thanks Narf, missed that part of the Type Juggling page earlier. You'd think that throwing a warning or notice would have been a helpful design choice on their part though, if encountering "undefined" behaviour. – thomasrutter Jun 12 '12 at 05:51
  • Well, I'd prefer PHP to be a bit more strict as well, but ... that's a kind of an unique feature that I don't think they'd be willing to deprecate any time soon. – Narf Jun 12 '12 at 05:55
  • I wouldn't want them to deprecate anything, just throw a notice or warning in order to be consistent with other times you access a non-existent array index, and warn developers about a potential mistake. – thomasrutter Jun 12 '12 at 06:02
  • 1
    There is no type juggling in the evaluation of `$myarray['banana']` (which is correctly exposed in this answer by quoting from the documentation). The PHP source code is the proof. The explanation and the link are provided by [this answer](http://stackoverflow.com/a/23538711/4265352). – axiac Mar 11 '15 at 11:18
10

There are three types which it might be valid to use the array derefence syntax on:

  • Arrays
  • Strings (to access the character at the given position)
  • Object (objects implementing the ArrayAccess interface)

For all other types, PHP just returns the undefined variable.

Array dereference is handled by the FETCH_DIM_R opcode, which uses zend_fetch_dimension_address_read() to fetch the element.

As you can see, there is a special case for NULLs, and a default case, both returning the undefined variable.

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
stackfu
  • 101
  • 1
  • 2
  • 1
    This is the correct answer, there is not type juggling on the evaluation of `$myarray['banana']`. – axiac Mar 11 '15 at 11:17
9

There is an active bug report started at 2006.

And in documentation it is a notice about this in String section. enter image description here

Mikhail Zhuravlev
  • 969
  • 2
  • 10
  • 22
  • That's great. As far as I know that wasn't in the documentation when I wrote this (or maybe I missed it because it was in the strings section), so thank you to whoever added/submitted that. – thomasrutter Aug 04 '16 at 23:39
  • 1
    For PHP 7.4, this now throws notices: https://wiki.php.net/rfc/notice-for-non-valid-array-container – glen Aug 31 '19 at 20:21
4

As of PHP 7.4, this behavior how emits a Notice. "Trying to access array offset on value of type null"

See the first item in this 7.4 migration page. https://www.php.net/manual/en/migration74.incompatible.php

This recently struck one of my colleagues in the butt because he neglected to validate the result of a database query before attempting to access column data from the variable.

$results = $this->dbQuery(...)
if($results['columnName'] == 1)
{
    // WHEN $results is null, this Notice will be emitted.
}

And I just noticed @Glen's comment, above, citing the relevant RFC. https://wiki.php.net/rfc/notice-for-non-valid-array-container