Search code examples
phpgoogle-app-engineserialization

PHP serialize() is not properly serializing stdClass object


I have an application running on Google App Engine (using PHP 5.5.38), and I'm using a Laravel package for caching query results.

This worked well for a similar project, but for this one, I get errors such as, "unserialize(): Error at offset 14 of 860 bytes" (the numbers vary, depending on what was serialized.)

The error occurs in a class that has only these two functions:

public function encode($data){
    return serialize($data);
}

public function decode($data){
    return unserialize($data);
}

I found that when testing the app locally, everything works correctly, and the serialized data looks something like this:

a:1:{i:0;O:8:"stdClass":27:{s:2:"id";i:2;s:10:"first_name";s:4:"Zach";...

But when I run it on App Engine with the same data, it returns this:

a:1:{i:0;O:8:"@*lass":27:{s:2:"id";i:2;s:10:"first_name";s:4:"Zach";...

It might not show here, but there are invisible characters next to the '*' (in notepad++, they show up as [ENQ] and [DLE]).

I believe that the call to unserialize() fails because the serialized data contains @*lass instead of stdClass, but I don't know what's causing it, or how to prevent it. I tried using str_replace, and it worked at first, but not for everything. I also made sure that PHP was using UTF-8 as the default charset.

EDIT: I modified the encode function to try to pinpoint the moment the trouble starts. I now have:

public function encode($data)
{
    $serialized = serialize($data);
    try{
        unserialize($serialized);
    } catch (\Exception $ex) {
        var_dump($serialized);
        die;
    }
    return $serialized;
}

And when it's executed on the server, it outputs:

a:1:{i:0;O:8:"@*lass":27:{s:2:"id";i:2;s:10:"first_name";s:4:"Zach"; ... 

So it seems like the problem starts with before anything is saved or unserialized.


Solution

  • Probably not an ideal fix, but this seems to work...

    public function encode($data)
    {
        return serialize(json_decode(json_encode($data), true));
    }
    
    public function decode($data)
    {
        return json_decode(json_encode(unserialize($data)));
    }
    

    The problem seemed to come from serializing an array of stdClass objects, so I figured it would help to convert stdClass to associative arrays.