What are the arrays that contain references to itself? What are circular references inside the array/object? How to serialize such entities in PHP?

While reading the manual page on the built-in function serialize() I came across the following quoted text :

You can even serialize() arrays that contain references to itself. Circular references inside the array/object you are serializing will also be stored. Any other reference will be lost.

I didn't understand what does mean by the array that contain references to itself?

I also didn't understand what are circular references inside the array/object?

The only thing I understood from the above text is I can generate a storable representation of such types of values using the built-in function serialize()

Also, there are no more code examples or explanation has been given with this regard.

I googled to understand the meaning of these types of entities specifically in PHP but I got nothing from Google.

Can someone please explain me these concepts with the help of easy to understand explanation accompanied with the suitable code examples. Examples would make things understand better.

1 answer

  • answered 2017-12-06 02:33 jh1711

    Examples are at the end of the answer.

    In (a) we try insert an array into itself. But a mechanism called copy on write kicks in and we insert $a into a copy of $a and end up with an array that contains an empty array. (b) is a little tricky. First we create an array that contains a reference to itself, but that means $b will itself be a reference. Then we pass $b to serialize, but serialize accepts a value only and thus will create a copy of $b. The output shows an array that contains an array that contains a reference to itself. The R:2; in the output indicates a reference to the second array. For some internal reason the count starts with 1 and not 0. (If you're really interested, I could lookup the reason, but for this question you can just accept it).

    Object act a little different. This is because objects in PHP are accessed by a an ID, and the copy on write only duplicates the ID structure and not the object itself. In the output of (c) you can see that this is by a small r. The number is just as above. But as seen in (d) you can also assign objects by reference and the small r will become a capital R. The output differs from (b), because while $d will be copied just like $b it again only affects the ID structure, and we see an object that contains a reference to itself. (e) utilizes the clone keyword to create an actual copy and serializes as such.

    Further Reading about PHP refereces.

    <?php
    
    $a = [];
    $a[] = $a;
    echo "\na: ".serialize($a);
    
    $b = [];
    $b[] =& $b;
    echo "\nb: ".serialize($b);
    
    $c = new stdClass();
    $c->c = $c;
    echo "\nc: ".serialize($c);
    
    $d = new stdClass();
    $d->d =& $d;
    echo "\nd: ".serialize($d);
    
    $e = new stdClass();
    $e->e = clone $e;
    echo "\ne: ".serialize($e);
    

    Output:

    a: a:1:{i:0;a:0:{}}
    b: a:1:{i:0;a:1:{i:0;R:2;}}
    c: O:8:"stdClass":1:{s:1:"c";r:1;}
    d: O:8:"stdClass":1:{s:1:"d";R:1;}
    e: O:8:"stdClass":1:{s:1:"e";O:8:"stdClass":0:{}}
    

    Link to play around with.

    Feel free to ask for clarification in comments the question is quite broad and I tried to keep it brief.