PHP 함수의 소스 코드 재구성/가져오기
함수의 소스 코드를 이름으로 프로그래밍 방식으로 가져올 수 있습니까?
예를 들어 다음과 같습니다.
function blah($a, $b) { return $a*$b; }
echo getFunctionCode("blah");
가능합니까?
함수/클래스 코드를 재구성하기 위한 php 자기 기술 함수가 있습니까?(소스 파일에서 바로 소스 코드를 가져오는 대신)
Java에는 http://java.sun.com/developer/technicalArticles/ALT/Reflection/ 가 있습니다.
Reflection을 사용하기 위한 제안을 확장합니다.다음과 같은 기능을 사용할 수 있습니다.
$func = new ReflectionFunction('myfunction');
$filename = $func->getFileName();
$start_line = $func->getStartLine() - 1; // it's actually - 1, otherwise you wont get the function() block
$end_line = $func->getEndLine();
$length = $end_line - $start_line;
$source = file($filename);
$body = implode("", array_slice($source, $start_line, $length));
print_r($body);
함수의 실제 코드를 알려줄 수 있는 것은 없습니다.이용 가능한 것은 Reflection뿐입니다.함수 클래스클래스의 경우 클래스 멤버(상수, 변수 및 메서드)와 가시성을 제공하는 ReflectionClass가 있지만 실제 코드는 없습니다.
회피책(소스 파일 읽기 포함):
리플렉션 사용Function:: export를 통해 함수가 선언된 파일 이름과 행 간격을 확인한 후 해당 행의 파일 내용을 읽습니다.문자열 처리를 사용하여 첫 번째 항목 사이의 값을 가져옵니다.{
마지막 '마지막'은}
.
리플렉션 API: 리플렉션 API입니다. ReflectionFunction::export
7.4PHP 7.4에서 되지 않습니다.
다른 운영체제(gnu/linux, windows, mac...)를 사용하여 프로그래밍합니다.이 때문에 코드에 캐리지 리턴이 다르기 때문에 이를 해결하기 위해 Brandon Horsley의 답변을 포크하여 다른 CR을 확인하고 함수 대신 클래스의 메서드에서 코드를 얻을 준비를 했습니다.
$cn = 'class_example';
$method = 'method_example';
$func = new ReflectionMethod($cn, $method);
$f = $func->getFileName();
$start_line = $func->getStartLine() - 1;
$end_line = $func->getEndLine();
$length = $end_line - $start_line;
$source = file($f);
$source = implode('', array_slice($source, 0, count($source)));
// $source = preg_split("/(\n|\r\n|\r)/", $source);
$source = preg_split("/".PHP_EOL."/", $source);
$body = '';
for($i=$start_line; $i<$end_line; $i++)
$body.="{$source[$i]}\n";
echo $body;
감사합니다.최종기능
function get_function($method,$class=null){
if (!empty($class)) $func = new ReflectionMethod($class, $method);
else $func = new ReflectionFunction($method);
$f = $func->getFileName();
$start_line = $func->getStartLine() - 1;
$end_line = $func->getEndLine();
$length = $end_line - $start_line;
$source = file($f);
$source = implode('', array_slice($source, 0, count($source)));
$source = preg_split("/".PHP_EOL."/", $source);
$body = '';
for($i=$start_line; $i<$end_line; $i++)
$body.="{$source[$i]}\n";
return $body;
}
도 , 그 된 후\ReflectionFunction
에는 시작 행과 끝 행에 대한 정보만 포함되어 있으며, 같은 행에 여러 개가 존재하고 네스트될 수 있는 경우에는 폐쇄 코드를 추출하기 위해 코드를 작성할 필요가 있다고 생각하거나 짧은 폐쇄 코드를 작성할 필요가 있다고 생각됩니다(죄송한 것보다 안전합니다).첫 번째, 두 번째, 두 번째 등 어느 쪽인지 알아야 합니다.이는 인수 목록 또는 어레이로 전달된 경우 어느 정도 알 수 있습니다.
제 경우엔 아주 구체적인 욕구가 있지만, 폐쇄 코드를 얻는 일반적인 해결책이 다른 사람들에게 유용할 수도 있습니다. 그래서 여기서 그만 두겠습니다.
<?php
namespace Phluid\Transpiler;
use ReflectionFunction;
final class Source
{
private const OPEN_NEST_CHARS = ['(', '[', '{'];
private const CLOSE_NEST_CHARS = [')', ']', '}'];
private const END_EXPRESSION_CHARS = [';', ','];
public static function doesCharBeginNest($char)
{
return \in_array($char, self::OPEN_NEST_CHARS);
}
public static function doesCharEndExpression($char)
{
return \in_array($char, self::END_EXPRESSION_CHARS);
}
public static function doesCharEndNest($char)
{
return \in_array($char, self::CLOSE_NEST_CHARS);
}
public static function readFunctionTokens(ReflectionFunction $fn, int $index = 0): array
{
$file = \file($fn->getFileName());
$tokens = \token_get_all(\implode('', $file));
$functionTokens = [];
$line = 0;
$readFunctionExpression = function ($i, &$functionTokens) use ($tokens, &$readFunctionExpression) {
$start = $i;
$nest = 0;
for (; $i < \count($tokens); ++$i) {
$token = $tokens[$i];
if (\is_string($token)) {
if (self::doesCharBeginNest($token)) {
++$nest;
} elseif (self::doesCharEndNest($token)) {
if ($nest === 0) {
return $i + 1;
}
--$nest;
} elseif (self::doesCharEndExpression($token)) {
if ($nest === 0) {
return $i + 1;
}
}
} elseif ($i !== $start && ($token[0] === \T_FN || $token[0] === \T_FUNCTION)) {
return $readFunctionExpression($i, $functionTokens);
}
$functionTokens[] = $token;
}
return $i;
};
for ($i = 0; $i < \count($tokens); ++$i) {
$token = $tokens[$i];
$line = $token[2] ?? $line;
if ($line < $fn->getStartLine()) {
continue;
} elseif ($line > $fn->getEndLine()) {
break;
}
if (\is_array($token)) {
if ($token[0] === \T_FN || $token[0] === \T_FUNCTION) {
$functionTokens = [];
$i = $readFunctionExpression($i, $functionTokens);
if ($index === 0) {
break;
}
--$index;
}
}
}
return $functionTokens;
}
}
그Source::readFunctionTokens()
메서드는 PHP의 출력과 유사한 출력을 반환합니다.\token_get_all()
이 함수는 폐쇄 시작부터 끝까지 코드만 필터링합니다.따라서 PHP의 구문적 요구에 따라 문자열과 배열이 혼합되어 있습니다. 여기를 참조하십시오.
사용방법:
$fn = [fn() => fn() => $i = 0, function () { return 1; }];
$tokens = Source::readFunctionTokens(new \ReflectionFunction($fn[1]), 1);
두 번째 arg는 가장 바깥쪽 범위의 첫 번째 닫힘 코드를 반환하고, 1은 가장 바깥쪽 범위의 두 번째 닫힘 코드를 반환합니다.코드는 매우 거칠고 생소한 것이므로 사용하고 싶다면 정리하는 것이 좋습니다.모든 구문이 유효하고 기본적인 구문 규칙을 위반할 수 있기 때문에 매우 안정적이고 성능이 있을 것입니다.
이 피드에 다른 맛의 훌륭한 코드를 추가하겠습니다.이건 나한테 효과가 있었어.
self::class를 ClassName::class로 대체하면 편집자가 파일을 쉽게 해결할 수 있습니다.
$methods = get_class_methods(self::class);
foreach ($methods as $method) {
$func = new ReflectionMethod(self::class, $method);
$f = $func->getFileName();
$start_line = $func->getStartLine() - 1;
$end_line = $func->getEndLine();
$length = $end_line - $start_line;
$source = file_get_contents($f);
$source = preg_split('/' . PHP_EOL . '/', $source);
$body = implode(PHP_EOL, array_slice($source, $start_line, $length));
echo $body . PHP_EOL . PHP_EOL;
}
언급URL : https://stackoverflow.com/questions/7026690/reconstruct-get-source-code-of-a-php-function
'programing' 카테고리의 다른 글
Vuex: 스테이트와 getter를 사용하는 경우 (0) | 2022.10.02 |
---|---|
stream_socket_enable_crypto() 수정 방법: SSL 작업이 코드 1로 실패했습니다. (0) | 2022.10.02 |
MySQL ORDER BY IN() (0) | 2022.10.02 |
datetime 기본값(mariadb) (0) | 2022.10.02 |
테이블의 모든 요소에 대해 조인 쿼리가 제대로 작동하지 않습니다. (0) | 2022.10.02 |