Cannot use string offset as an array in php

I had this error for the first time ever while trying to debug some old legacy code, running now on PHP 7.30. The simplified code looked like this:

$testOK = true;

if ($testOK) {
    $x['error'][] = 0;
    $x['size'][] = 10;
    $x['type'][] = 'file';
    $x['tmp_name'][] = 'path/to/file/';
}

The simplest fix possible was to declare $x as array() before:

$x = array();

if ($testOK) {
    // same code
}

For PHP4

...this reproduced the error:

$foo    = 'bar';
$foo[0] = 'bar';

For PHP5

...this reproduced the error:

$foo = 'bar';

if (is_array($foo['bar']))
    echo 'bar-array';
if (is_array($foo['bar']['foo']))
    echo 'bar-foo-array';
if (is_array($foo['bar']['foo']['bar']))
    echo 'bar-foo-bar-array';

(From bugs.php.net actually)

Edit,

so why doesn't the error appear in the first if condition even though it is a string.

Because PHP is a very forgiving programming language, I'd guess. I'll illustrate with code of what I think is going on:

$foo = 'bar';
// $foo is now equal to "bar"

$foo['bar'] = 'foo';
// $foo['bar'] doesn't exists - use first index instead (0)
// $foo['bar'] is equal to using $foo[0]
// $foo['bar'] points to a character so the string "foo" won't fit
// $foo['bar'] will instead be set to the first index
// of the string/array "foo", i.e 'f'

echo $foo['bar'];
// output will be "f"

echo $foo;
// output will be "far"

echo $foo['bar']['bar'];
// $foo['bar'][0] is equal calling to $foo['bar']['bar']
// $foo['bar'] points to a character
// characters can not be represented as an array,
// so we cannot reach anything at position 0 of a character
// --> fatal error

I was able to reproduce this once I upgraded to PHP 7. It breaks when you try to force array elements into a string.

$params = '';
foreach ($foo) {
  $index = 0;
  $params[$index]['keyName'] = $name . '.' . $fileExt;
}

After changing:

$params = '';

to:

$params = array();

I stopped getting the error. I found the solution in this bug report thread. I hope this helps.


I was fighting a similar problem, so documenting here in case useful.

In a __get() method I was using the given argument as a property, as in (simplified example):

function __get($prop) {
     return $this->$prop;
}

...i.e. $obj->fred would access the private/protected fred property of the class.

I found that when I needed to reference an array structure within this property it generated the Cannot use String offset as array error. Here's what I did wrong and how to correct it:

function __get($prop) {
     // this is wrong, generates the error
     return $this->$prop['some key'][0];
}

function __get($prop) {
     // this is correct
     $ref = & $this->$prop;
     return $ref['some key'][0];
}

Explanation: in the wrong example, php is interpreting ['some key'] as a key to $prop (a string), whereas we need it to dereference $prop in place. In Perl you could do this by specifying with {} but I don't think this is possible in PHP.

Tags:

Php