Skip to content

Instantly share code, notes, and snippets.

@simivar
Last active November 4, 2023 23:27
Show Gist options
  • Save simivar/037b13a9bbd53ae5a092d8f6d9828bc3 to your computer and use it in GitHub Desktop.
Save simivar/037b13a9bbd53ae5a092d8f6d9828bc3 to your computer and use it in GitHub Desktop.
PHP function to reverse print_r function
<?php
/**
* I've published a fully-tested Composer library with type-casting.
* @see https://github.com/simivar/reverse-print-r
*/
/**
* Matt: core
* Trixor: object handling
* lech: Windows suppport
* simivar: null support
*
* @see http://php.net/manual/en/function.print-r.php
**/
function print_r_reverse($input) {
$lines = preg_split('#\r?\n#', trim($input));
if (trim($lines[ 0 ]) != 'Array' && trim($lines[ 0 ]) != 'stdClass Object') {
// bottomed out to something that isn't an array or object
if ($input === '') {
return null;
}
return $input;
} else {
// this is an array or object, lets parse it
$match = array();
if (preg_match("/(\s{5,})\(/", $lines[ 1 ], $match)) {
// this is a tested array/recursive call to this function
// take a set of spaces off the beginning
$spaces = $match[ 1 ];
$spaces_length = strlen($spaces);
$lines_total = count($lines);
for ($i = 0; $i < $lines_total; $i++) {
if (substr($lines[ $i ], 0, $spaces_length) == $spaces) {
$lines[ $i ] = substr($lines[ $i ], $spaces_length);
}
}
}
$is_object = trim($lines[ 0 ]) == 'stdClass Object';
array_shift($lines); // Array
array_shift($lines); // (
array_pop($lines); // )
$input = implode("\n", $lines);
$matches = array();
// make sure we only match stuff with 4 preceding spaces (stuff for this array and not a nested one)
preg_match_all("/^\s{4}\[(.+?)\] \=\> /m", $input, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
$pos = array();
$previous_key = '';
$in_length = strlen($input);
// store the following in $pos:
// array with key = key of the parsed array's item
// value = array(start position in $in, $end position in $in)
foreach ($matches as $match) {
$key = $match[ 1 ][ 0 ];
$start = $match[ 0 ][ 1 ] + strlen($match[ 0 ][ 0 ]);
$pos[ $key ] = array($start, $in_length);
if ($previous_key != '') {
$pos[ $previous_key ][ 1 ] = $match[ 0 ][ 1 ] - 1;
}
$previous_key = $key;
}
$ret = array();
foreach ($pos as $key => $where) {
// recursively see if the parsed out value is an array too
$ret[ $key ] = print_r_reverse(substr($input, $where[ 0 ], $where[ 1 ] - $where[ 0 ]));
}
return $is_object ? (object)$ret : $ret;
}
}
@MagicTrixor
Copy link

if (trim($lines[ 0 ]) != 'Array' && trim($lines[ 0 ] != 'stdClass Object')) {
has a bug, it should be
if (trim($lines[ 0 ]) != 'Array' && trim($lines[ 0 ]) != 'stdClass Object') {

Cool for putting it here :)

@simivar
Copy link
Author

simivar commented Jan 17, 2019

@MagicTrixor: fixed

@digitalowlnyc
Copy link

Thanks for sharing, what is the license on this code? Also, any interest in turning it into a composer package (I'm willing to set that up if needed).

@simivar
Copy link
Author

simivar commented Nov 9, 2019

@digitalowlnyc it was first posted on php.net note's section on print_r. From what I gather all notes are shared on the same license as PHP documentation (see here), so it's CC BY 3.0.

I don't think there is a composer package for that but I'll try to set something up soon and refactor it a little. If you feel like you need it now feel free to publish it yourself as it is CC BY 3.0.

@divinity76
Copy link

divinity76 commented Mar 10, 2020

you can use

if (trim($lines[ 0 ]) != 'Array' && !preg_match('/^\S+?\ Object$/',trim($lines[ 0 ])))

to support objects other than stdClass Object, for example it fixed this:

Replay Object
(
    [id] => 1106
    [date] => 2020-02-22 09:57:28
    [json] => Array
        (
            [id] => CForEIS28JPUV
            [name] => Kontor
            [type] => Office
            [event] => Update
            [subtype] => Office
            [customerId] => S3
        )

    [url] => http://www.eS322
)

@simivar
Copy link
Author

simivar commented Mar 10, 2020

@divinity76 could you provide the source code of Replay class? It will make nice test-case.

@divinity76
Copy link

divinity76 commented Mar 11, 2020

nothing more fancy than

class Replay
{

    public $id;

    public $date;

    public $json;
}

.. the url-attribute was added post-construction

@simivar
Copy link
Author

simivar commented Mar 20, 2020

I've published a fully-tested Composer library with type-casting. See simivar/reverse-print-r if you want to use that.

/cc @divinity76 @digitalowlnyc

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment