Search code examples
phphttp-status-code-500php-8.1

jQuery AJAX call broken under PHP 8.X (PHP 8 Uncaught TypeError: array_key_exists() error)


I will try to be as much explicative as possible.

I have a PHP+jQuery application (some sort of a text game) where the system works reading and writing JSON files with AJAX all the time. Everything is absolutely perfect under PHP 7.4, however, when I upgrade to 8.0 or 8.1 (my hosting is forcing me) the AJAX breaks.

Inspecting the JS console, right after the very first AJAX call, I get a ERROR 500. So, I assumed it was happening in the PHP side and I was right. I did take a look in the apache logs and found a PHP fatal error happening there — But note that under PHP7.4, there are no problems at all.

The error in my Apache log:

PHP Fatal error:  Uncaught TypeError: array_key_exists():
Argument #2 ($array) must be of type array,
stdClass given in /home/xxx/zzz.com/motor/FileDriver.php:36,
referer: https://zzz.com/yyy/xxx/

And this is the PHP file where the error happens, line 36:

function save() {
    $n = func_num_args();
    $g = func_get_args();

    $data = json_decode(file_get_contents($g[0]));
    
    if (!array_key_exists($g[1], $data))
        $data->{$g[1]} = new StdClass();

    if (($n == 4) && (!array_key_exists($g[2], $data->{$g[1]})))
        $data->{$g[1]}->{$g[2]} = new StdClass();

    if ($n == 3)
        $data->{$g[1]} = $g[2];
    else if ($n == 4)
        $data->{$g[1]}->{$g[2]} = $g[3];

    unlink($g[0]);
    file_put_contents($g[0], json_encode($data, JSON_PRETTY_PRINT));
}

The error happens right here:

    $data = json_decode(file_get_contents($g[0]));
    // THE ERROR BELOW!
    if (!array_key_exists($g[1], $data))
        $data->{$g[1]} = new StdClass();

I tried to add the $assoc parameter to PHP json_decode() function, but it did not help. I really have no idea how to solve that, other than downgrading to PHP 7.4... however, can't do it anymore.

EDITED: Removed irrelevant code, image and information.

EDITED2: Adjusted the title to a more explicative sentence.


Solution

  • The AJAX call hasn't failed. The error message clearly points at PHP, so all this JavaScript is irrelevant.

    Looking at the error message and the PHP code you have posted the variable $data is an object.

    The documentation for array_key_exists() says this:

    For backward compatibility reasons, array_key_exists() will also return true if key is a property defined within an object given as array. This behaviour is deprecated as of PHP 7.4.0, and removed as of PHP 8.0.0.

    To check whether a property exists in an object, property_exists() should be used.

    You should update line 36 to this:

    if (!property_exists($data,$g[1]))
    

    Note that the order of parameters is reversed from array_key_exists()