Search code examples
phpvar-dump

Convert var_dump of array back to array variable


I have never really thought about this until today, but after searching the web I didn't really find anything. Maybe I wasn't wording it right in the search.

Given an array (of multiple dimensions or not):

$data = array('this' => array('is' => 'the'), 'challenge' => array('for' => array('you')));

When var_dumped:

array(2) { ["this"]=> array(1) { ["is"]=> string(3) "the" } ["challenge"]=> array(1) { ["for"]=> array(1) { [0]=> string(3) "you" } } }

The challenge is this: What is the best optimized method for recompiling the array to a useable array for PHP? Like an undump_var() function. Whether the data is all on one line as output in a browser or whether it contains the line breaks as output to terminal.

Is it just a matter of regex? Or is there some other way? I am looking for creativity.

UPDATE: Note. I am familiar with serialize and unserialize folks. I am not looking for alternative solutions. This is a code challenge to see if it can be done in an optimized and creative way. So serialize and var_export are not solutions here. Nor are they the best answers.


Solution

  • var_export or serialize is what you're looking for. var_export will render a PHP parsable array syntax, and serialize will render a non-human readable but reversible "array to string" conversion...

    Edit Alright, for the challenge:

    Basically, I convert the output into a serialized string (and then unserialize it). I don't claim this to be perfect, but it appears to work on some pretty complex structures that I've tried...

    function unvar_dump($str) {
        if (strpos($str, "\n") === false) {
            //Add new lines:
            $regex = array(
                '#(\\[.*?\\]=>)#',
                '#(string\\(|int\\(|float\\(|array\\(|NULL|object\\(|})#',
            );
            $str = preg_replace($regex, "\n\\1", $str);
            $str = trim($str);
        }
        $regex = array(
            '#^\\040*NULL\\040*$#m',
            '#^\\s*array\\((.*?)\\)\\s*{\\s*$#m',
            '#^\\s*string\\((.*?)\\)\\s*(.*?)$#m',
            '#^\\s*int\\((.*?)\\)\\s*$#m',
            '#^\\s*bool\\(true\\)\\s*$#m',
            '#^\\s*bool\\(false\\)\\s*$#m',
            '#^\\s*float\\((.*?)\\)\\s*$#m',
            '#^\\s*\[(\\d+)\\]\\s*=>\\s*$#m',
            '#\\s*?\\r?\\n\\s*#m',
        );
        $replace = array(
            'N',
            'a:\\1:{',
            's:\\1:\\2',
            'i:\\1',
            'b:1',
            'b:0',
            'd:\\1',
            'i:\\1',
            ';'
        );
        $serialized = preg_replace($regex, $replace, $str);
        $func = create_function(
            '$match', 
            'return "s:".strlen($match[1]).":\\"".$match[1]."\\"";'
        );
        $serialized = preg_replace_callback(
            '#\\s*\\["(.*?)"\\]\\s*=>#', 
            $func,
            $serialized
        );
        $func = create_function(
            '$match', 
            'return "O:".strlen($match[1]).":\\"".$match[1]."\\":".$match[2].":{";'
        );
        $serialized = preg_replace_callback(
            '#object\\((.*?)\\).*?\\((\\d+)\\)\\s*{\\s*;#', 
            $func, 
            $serialized
        );
        $serialized = preg_replace(
            array('#};#', '#{;#'), 
            array('}', '{'), 
            $serialized
        );
    
        return unserialize($serialized);
    }
    

    I tested it on a complex structure such as:

    array(4) {
      ["foo"]=>
      string(8) "Foo"bar""
      [0]=>
      int(4)
      [5]=>
      float(43.2)
      ["af"]=>
      array(3) {
        [0]=>
        string(3) "123"
        [1]=>
        object(stdClass)#2 (2) {
          ["bar"]=>
          string(4) "bart"
          ["foo"]=>
          array(1) {
            [0]=>
            string(2) "re"
          }
        }
        [2]=>
        NULL
      }
    }