Страницы

Поиск по вопросам

понедельник, 17 июня 2019 г.

Вывод lambda функции, в виде текста

Приветствую! Знатоки выручайте, долгое время уже пытаюсь разобраться с этим вопросом и никак не могу найти информацию, а точнее нашел, но не то. Вообщем сама задача.
Есть массив, который содержит в себе lambda функции:
$functs = ['name' => function() { return 1; }];
Мне нужно создать для него редактирование, казалось бы все так просто, взять циклом пробежаться и всунуть все в input и textarea поля.
Но возникла проблема сами функции они не выводятся так как нужно. А нужно чтобы они также выводились как определены в массиве, то есть строкой.
function() { return 1; }
Прям точно также - как и определены в значении массива. Пробовал делать так:
$func= new ReflectionFunction($functs['name']); var_dump($func->__toString());
Но! Выводится мусор, не то, что нужно:
Closure [ function {closure} ] { @@ .....\index.php 11 - 13 }
Уже какой день бьюсь в этом направлении и никак не могу решить задачу, чтобы было ключ массива в 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; }
Теперь нормально работает.

Комментариев нет:

Отправить комментарий