Приветствую! Знатоки выручайте, долгое время уже пытаюсь разобраться с этим вопросом и никак не могу найти информацию, а точнее нашел, но не то.
Вообщем сама задача.
Есть массив, который содержит в себе lambda функции:
$functs = ['name' => function() {
return 1;
}];
Мне нужно создать для него редактирование, казалось бы все так просто, взять циклом пробежаться и всунуть все в input и textarea поля.
Но возникла проблема сами функции они не выводятся так как нужно.
А нужно чтобы они также выводились как определены в массиве, то есть строкой.
function() {
return 1;
}
Прям точно также - как и определены в значении массива.
Пробовал делать так:
$func= new ReflectionFunction($functs['name']);
var_dump($func->__toString());
Но! Выводится мусор, не то, что нужно:
Closure [
Уже какой день бьюсь в этом направлении и никак не могу решить задачу, чтобы было ключ массива в input, а значение в textarea.
То есть вот так:
Пожалуйста помогите или пните в правильном направлении.
UPD:
Массив может быть любого вида:
Хоть такой:
$functs = ['name' => function() {return 1;},'m'=>fucntion() {}];
В одну строку.
Пробовал решить так:
function closure(Closure $closure) {
$function = new ReflectionFunction($closure);
$file = file($function->getFileName());
for ($i = $function->getStartLine() - 1; $i < $function->getEndLine(); $i++) {
$str .= $file[$i];
}
$funct = mb_substr($str, mb_stripos($str, 'function', 0, 'utf-8'), -1, 'utf-8');
$funct = mb_substr($funct, 0, mb_strripos($funct, '}', 0, 'utf-8')+1, 'utf-8');
return $funct;
}
Работает, но только если размер массива 1.
То есть такой:
$functs = ['name' => function() {return 1;}];
а в случае:
(new MyClosure($closure))->__toString();
возникает LogicException, что не совсем гуд, исключено, чтобы это было.
нужно решение, чтобы в любом написании массива с lambda функциями.
Кстате, ссылка с приведенным алгоритмом, не пашет тоже.
Незнаю, как поправить свою функцию, так, чтобы отследить правильную позицию завершения блока функции " } ", а не искать конец " } ", а то получается, что он захватывает все и получается хрень.
Похоже и длину строки надо считать и т.д., формула нужна, как верно отследить.
Выручайте, не врублюсь, какое условие написать?
Ответ
Пришлось делать запись данных уже в нужном виде (если посоветуете, что-то, лучше, буду рад):
public final function arrayDump(array $array): string {
if (1 <= sizeof($array)) {
$arr = [];
foreach ($array as $key => $value) {
$key = addslashes($key);
if (is_callable($value)) {
$value = $this->closure($value);
$arr[] = "'{$key}' => {$value}";
} else if (is_string($value)) {
$arr[] = "'{$key}' => '" . addslashes($value) . "'";
} else if (is_float($value) || is_double($value)) {
$value = (double) $value;
$arr[] = "'{$key}' => {$value}";
} else if (is_int($value)) {
$value = (int) $value;
$arr[] = "'{$key}' => {$value}";
} else if (is_object($value)) {
$arr[] = "'{$key}' => '" . serialize($value) . "'";
}
}
return"[
\t" . join("\t", $arr) . "
];";
}
return'';
}
Ну и сам метод closure
public final function closure(Closure $closure): string {
$func = 'function(';
$function = new ReflectionFunction($closure);
$params = [];
$parameters = $function->getParameters();
foreach ($parameters as $param) {
$string = '';
if ($param->isArray()) {
$string .= 'array ';
} else if ($param->getClass()) {
$string .= $param->getClass()->name . ' ';
}
if ($param->isPassedByReference()) {
$string .= '&';
}
$string .= '$' . $param->name;
if ($param->isOptional()) {
$string .= ' = ' . var_export($param->getDefaultValue(), true);
}
$params[] = $string;
}
unset($parameters, $param);
$func .= join(', ', $params) . ') {' . PHP_EOL;
$lines = file($function->getFileName());
$start = $function->getStartLine();
$end = $function->getEndLine();
for ($l = $start; $l < $end; ++$l) {
$func .= $lines[$l];
}
return $func;
}
Теперь нормально работает.