I have this script to format var_export's result string. The information in the output is good, but I need know if the code performance is good or if it can be improved.
https://wtools.io/php-sandbox/biDk
<?php
#Variable:
$Test = [];
$Test['Check1'] = null;
$Test['Check2'] = [];
$Test['Check2']['int'] = 20;
$Test['Check2']['float'] = 20.35;
$Test['Check2']['string'] = 'Hello World';
$Test['Check2']['bolean'] = true;
$Test['Check2']['array'] = [];
$Test['Check2']['array']['data'] = 'Array Text';
class Example {
function foo_function() {
return "Hello World! Object";
}
}
$var_object = new Example;
$Test['Check2']['array']['object'] = $var_object;
$Test['Check2']['array']['object2'] = $var_object->foo_function();
#Script Type:
function myGetType($var) {
if (is_null($var) OR $var == 'null' OR $var == 'NULL') {
return "(NULL)";
}
if (is_array($var)) {
return "array";
}
if (in_array($var, array("true", "false"), true)) {
return "boolean";
}
if ((int) $var == $var && is_numeric($var)) {
return "integer" . '(' . strlen($var) . ')';
}
if ((float) $var == $var && is_numeric($var)) {
return "float" . '(' . strlen($var) . ')';
}
if (is_object($var)) {
return "object";
}
if (is_resource($var)) {
return "resource";
}
if (is_string($var)) {
return "string" . '(' . strlen($var) . ')';
}
return "unknown";
}
#Script Analisis:
function VarExportFormat($Var) {
$textvar = '';
$textvar = var_export($Var, true);
$textvar = preg_replace("/^([ ]*)(.*)/m", '1ドル1ドル2ドル', $textvar);
$textvarArr = preg_split("/\r\n|\n|\r/", $textvar);
# Analisis del tipo.
foreach ($textvarArr as $key => $value) {
preg_match('~=>\\s(.*?),~', $value, $newvalue);
if (!empty($newvalue)) {
$newvalue[1] = str_replace("'", "", $newvalue[1]);
$typeval = myGetType($newvalue[1]);
$value = str_replace("=> ", "=> " . $typeval . ': ', $value);
$textvarArr[$key] = $value;
}
}
$textvarArr = preg_replace(["/\s*array\s\($/", "/\)(,)?$/", "/\s=>\s$/"], [NULL, ']1ドル', ' => array ['], $textvarArr);
$textvar = join(PHP_EOL, array_filter(["array ["] + $textvarArr));
if (substr($textvar, -1) == '[') {
$textvar = str_replace("[", "[]", $textvar);
}
$textvar = str_replace("__set_state", "__set_state(object)", $textvar);
$textvar = highlight_string("<?php \n#output of Variable:\n" . $textvar . ";\n?>", true);
return $textvar;
}
echo VarExportFormat($Test);
1 Answer 1
Your script is like a var_export()
-var_dump()
hybrid with flare (I've not come across highlight_string()
before -- pretty cool).
I ran some more tests with a few samples that I had laying around and noticed that your code is having some difficulties accessing the written "resource" branch. I tested with
fopen($filename, 'r')
; thevar_export()
evaluation of a resource isNULL
andvar_dump()
returnsresource(5) of type (stream)
. Because your script is founded onvar_export()
, it will fail to dignify theresource
type data, I think you [sh/c]ould remove that from your battery of checks.Miscellaneous gotchas include:
['a => key' => 'something']
and
['multiline' => 'line1 line2']
These will break your regex-based parsing -- of course, the former is going to be a much less common occurrence versus the latter.
You can safely remove some useless declarations:
$Test = [];
and$textvar = '';
As a general rule, I prefer to never use
OR
orAND
in my conditional statements as a matter of consistency and as a means to avoid fringe precedence issues.preg_replace("/^([ ]*)(.*)/m", '1ドル1ドル2ドル', $textvar);
This pattern/function is over-performing. It doesn't make any sense to pick up the second capture group, just to put it back down unaltered. In fact, there is no need for capture groups or character classes for this task. I will also recommend that you use a consistent pattern delimiter for all patterns in your script. A tilde is a good/popular choice because it shouldn't interfere with any of your patterns and will help to prevent any accidental typos and escaping problems elsewhere. To double the leading whitespace on each line, just use this (there's no use doubling zero whitespaces, so match one-or-more with+
):preg_replace('~^ +~m', '0ドル0ドル', $textvar);
$textvarArr = preg_split("/\r\n|\n|\r/", $textvar)
is more succinctly written as:$textvarArr = preg_split("~\R~", $textvar)
Whenever I see
preg_match()
called inside of a loop so that replacement actions can be performed, this is a classic indicator thatpreg_replace_callback()
should be called.$textvarArr = preg_split("~\R~", $textvar); foreach ($textvarArr as $key => $value) { preg_match('~=>\\s(.*?),~', $value, $newvalue); if (!empty($newvalue)) { $newvalue[1] = str_replace("'", "", $newvalue[1]); $typeval = myGetType($newvalue[1]); $value = str_replace("=> ", "=> " . $typeval . ': ', $value); $textvarArr[$key] = $value; } }
can become:
$textvar = preg_replace_callback( "~ => \K\V+(?=,)~", function ($m) { return myGetType(str_replace("'", "", $m[0])) . ": {$m[0]}"; }, $textvar ); // then proceed with something like... $textvarArr = preg_replace(["/\s*array\s\($/", "/\)(,)?$/", "/\s=>\s$/"], [NULL, ']1ドル', ' => array ['], preg_split("~\R~", $textvar));
I've got to say that this looks a little dangerous...
if (substr($textvar, -1) == '[') { $textvar = str_replace("[", "[]", $textvar); }
I mean, you are checking the final character, then doing a full text scan and replace operation. This deserves a bit of double-checking. Don't you only mean to close the final square brace? Maybe...
if (substr($textvar, -1) == '[') { $textvar .= "]"; }
I didn't get a chance to properly review (but it could probably use a little polish/simplifying):
$textvarArr = preg_replace(["/\s*array\s\($/", "/\)(,)?$/", "/\s=>\s$/"], [NULL, ']1ドル', ' => array ['], preg_split("~\R~", $textvar));
$textvar = join(PHP_EOL, array_filter(["array ["] + $textvarArr));
I ran our outputs on a diffchecker program to be sure that my script returns the exact same output as yours.
Overall, an interesting exercise, good job.
-
1\$\begingroup\$ I have no idea the ramifications of rebuilding this script on that function. I have only ever seen that function used on this site (never anywhere else in the SE network). I am happy for you to demonstrate. \$\endgroup\$mickmackusa– mickmackusa2019年10月05日 13:35:56 +00:00Commented Oct 5, 2019 at 13:35
-
1\$\begingroup\$ I don't see
resource
on that list either. \$\endgroup\$mickmackusa– mickmackusa2019年10月05日 13:41:15 +00:00Commented Oct 5, 2019 at 13:41 -
\$\begingroup\$ I need to clarify that the main variable result of var_export is a string and therefore I cannot use is_string (), is_float, is_integer, because is_string will always be valid, I must evaluate if the string can be converted to the other types to validate them so use (int) (float) etc, and then I make the comparison == (without type) \$\endgroup\$Minos Framework– Minos Framework2019年10月05日 15:43:17 +00:00Commented Oct 5, 2019 at 15:43
-
1\$\begingroup\$ i have make other post result of it... if you can help me with this: stackoverflow.com/questions/58458584/… \$\endgroup\$Minos Framework– Minos Framework2019年10月22日 14:37:46 +00:00Commented Oct 22, 2019 at 14:37
-
1\$\begingroup\$ Gotta sleep. Maybe tomorrow. \$\endgroup\$mickmackusa– mickmackusa2019年10月22日 14:42:51 +00:00Commented Oct 22, 2019 at 14:42
(string)$string == $string
can be a replacement aswell foris_string()
, same trick you did with int and floats.. \$\endgroup\$(object)$var == $var
and(array)$var == $var
can also works aswell to replace is_object and is_array but performance is more depending on the object or array size and or PHP version, this trick does not scale that that well as the int, string types.. Might be interesting to test with? \$\endgroup\$var_export()
returns parseable PHP... \$\endgroup\$