Я хотел отправить функцию, используя какую-то передачу в другой скрипт.
Для этого мне нужно было упаковать эту функцию в полезную нагрузку PHP (оценить ее как строку в другом файле PHP, возможно, на другом сервере).
$abc = "testABC";
$xyz = new TestClass();
$test = true;
$x = function () use ($test, $xyz, $abc) {
echo $abc;
var_dump($test, $xyz);
};
Эта функция будет упакована в строку вроде этой:
$payload = function () {
$test = unserialize('b:1;');
$xyz = unserialize('O:9:"TestClass":0:{}');
$abc = unserialize('s:7:"testABC";');
echo $abc;
var_dump($test, $xyz);
};
Чтобы сделать это, я написал следующую функцию, которая извлекает код функции, соответствует любому use(...)
пункты и переименовывает переменную это называется. В конце концов, он назначит use(...)
переменные в виде несериализуемой строки.
function packAnonFunction($payload, ...$args) {
$func = new ReflectionFunction($payload);
$filename = $func->getFileName();
$start_line = $func->getStartLine() - 1;
$end_line = $func->getEndLine();
$length = $end_line - $start_line;
$source = file($filename);
$body = implode("", array_slice($source, $start_line, $length));
$body = preg_replace('/(\$[a-z]+)\ \=\ function/', '\\$payload = function', $body);
if(preg_match('/use\s\((\$[a-zA-Z0-9]+(?:,\s\$[a-zA-Z0-9]+)*)\)/', $body, $matches)) {
$vars = $matches[1];
if(strpos($vars, ', ') !== false) {
$parts = explode(', ', $vars);
} else {
$parts = [$vars];
}
$return = [];
foreach($parts as $key => $variable) {
$return[$variable] = $args[$key];
}
$variableString = "";
foreach($return as $var => $value) {
$value = serialize($value);
$variableString .= "\t{$var} = unserialize('{$value}');\n";
}
$body = str_replace(" use (" . $vars . ")", "", $body);
$body = str_replace("{\n", "{\n" . $variableString, $body);
}
return $body;
}
Вы можете просто использовать это так:
$abc = "testABC";
$xyz = new TestClass();
$test = true;
$x = function () use ($test, $xyz, $abc) {
echo $abc;
var_dump($test, $xyz);
};
echo packAnonFunction($x, $test, $xyz, $abc);
Единственное отставание, от которого я не смог обойтись, это то, что вам придется ставить аргументы ($test, $xyz, $abc
) в том же порядке, в котором вы use(...)
заявление.
Смотрите это в действии: https://3v4l.org/89pXm
Так что вы думаете об этом?
Других решений пока нет …