Search code examples
phparraysphp-7

PHP 7 Upgrade Uncaught exception 'Error' with message 'Cannot use string offset as an array'


I recently upgraded to PHP 7.2 and i've been running some old legacy code for a stupid record keeping system. Basically it holds an array of contest_id's and the entries to each contest.

/*
@Use: Adds entries into the active contest for a given member.
@Param: $user_id - INT
@Param: $entries - INT
*/
function add_vip_entries($user_id, $entries) {
  $user_data = get_user_meta( $user_id, 'all_contests', true );
  $contest_id = get_active_contest();
  if ($contest_id !== 0) {
    if (isset($user_data['all_contests'][$contest_id]['entries'])) {
      $user_data['all_contests'][$contest_id]['entries'] = intval($user_data['all_contests'][$contest_id]['entries'] + $entries);
    } else {
      $user_data['all_contests'][$contest_id]['entries'] = $entries;
    }
    update_user_meta( $user_id, 'all_contests', $user_data );
  }
}

This used to work fine but now if it's the first time the user gain entries to a given contest I get the following error.

Uncaught exception 'Error' with message 'Cannot use string offset as an array'

And it triggers on this exact line:

$user_data['all_contests'][$contest_id]['entries'] = $entries;

How Can I replicate the behavior it had in PHP7.0? It used to simply push create the data structure or if it was a brand new contest push a new contest ID and set of entries. Now it errors. I tried to edit into this

$user_data = array('all_contests' => array($contest_id => array('entries' => $entries)));

But this causes an issue where if a new contest ID is introduced it will set the data structure to only contain the contest ID and entry pair being set.


Solution

  • The issue here is that you can't successfully play with a STRING variable using ARRAY keys unless you are simply trying to return the Nth character of the string using $myString[n].

    Repro:

    $x = 'hello'
    echo $x[1]; // returns 'e', i.e. the 1st char (0 based) of 'hello'
    $x[4] = 'x';
    echo $x; // returns 'hellx';
    
    $x['my_key'] = 5; // Error illegal string offset
    

    I.e. you can use array keys to access the character of a string (i.e. the string offset, but it will only allow you to use a valid offset within the length of the string. You can't use a random key on a variable already initialized as a string.

    You need to make get_user_data return an array at all times. If it is empty, return [].

    $user_data = get_user_meta( $user_id, 'all_contests', true ) ?: [];