0

I'm running into a weird issue where if I try to serialize an array of objects of the same class, where that class has implemented the Serializable interface and in the serializable interface returns the serialized instance of another class, the array items after the first couple are considered recursive.

Here is a test case:

<?php

class HelloWorld implements Serializable {
    public $test;

    public function __construct($str)
    {
        $this->test = $str;
    }

    public function serialize()
    {
        $simple = null;
        $simple = new Simple();
        $simple->test = $this->test;
        return serialize($simple);
    }

    public function unserialize($str)
    {
        $simple = unserialize($str);
        $this->test = $simple->test;
    }
}

class Simple
{
    public $test;
}

$list = array(
    new HelloWorld('str1'),
    new HelloWorld('str2'),
    new HelloWorld('str3'),
    new HelloWorld('str4'),
    new HelloWorld('str5'),
    new HelloWorld('str6'),
    new HelloWorld('str7'),
    new HelloWorld('str8'),
    new HelloWorld('str9'),
);

$str = serialize($list);
echo $str . "\n";

// var_dump(unserialize($str));

Uncomment the last line and enjoy a php segmentation fault.

Does anyone know why this is or how to fix it? This doesn't seem to be an issue if what is being serialized in HelloWorld::serialize() is an array or a primitive value.

Update:

Here is the output from the above code:

a:9:{i:0;C:10:"HelloWorld":39:{O:6:"Simple":1:{s:4:"test";s:4:"str1";}}i:1;C:10:"HelloWorld":4:{r:3;}i:2;C:10:"HelloWorld":4:{r:3;}i:3;C:10:"HelloWorld":4:{r:3;}i:4;C:10:"HelloWorld":4:{r:3;}i:5;C:10:"HelloWorld":4:{r:3;}i:6;C:10:"HelloWorld":4:{r:3;}i:7;C:10:"HelloWorld":4:{r:3;}i:8;C:10:"HelloWorld":4:{r:3;}}

The issue is the r:4; stuff on the second and following records.

1 Answer 1

1

DAMN! Sorry, I read your question wrong. Thought you wanted to print all of them.

You need simple to be serializable. Otherwise it won't work, in order to serialize you need could use something like this:

class HelloWorld implements Serializable 
{
    public $test;

    public function __construct($str)
    {
         $this->test = $str;
    }

    public function serialize()
    {
        return serialize($this->test);
    }

    public function unserialize($str)
    {
        $simple = unserialize($str);
        $this->test = $simple;
    }
}

The simple class is not needed. Remember that $this->data will always have to be serializable.

Sign up to request clarification or add additional context in comments.

2 Comments

My example code is simplified from the original case to better illustrate the issue and remove some of our supporting libraries from the equation. In my original codebase, HelloWorld corresponds to a model class. Simple corresponds to a generic data-only class for templates. The reason I want the two classes like this is so that on unserialize, I can recreate the database connections. This is legacy code, so I can't rearchitect it.
It's perfectly fine. You just have to make sure that the Simple class is serializable and you will just be able to serialize and unserialize at will (without rebuilding the object). You can recreate the database connections when unserializing. That's exactly what I do in my code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.