在javascript中,任何函数基本上都是一个对象,您可以在其上调用(function(){})。toString()以将其底层代码作为字符串。
我正在开发一个旨在用PHP完成工作的函数。 到目前为止看起来像这样:
function fn_to_string($fn, $strip_comments = true) {
static $contents_cache = array();
static $nl = "\r\n"; # change this to how you want
if(!is_callable($fn)) return ''; # it should be a function
if(!class_exists('ReflectionFunction')) return ''; # PHP 5.1 I think
# get function info
$rfn = new ReflectionFunction($fn);
$file = $rfn->getFileName();
$start = $rfn->getStartLine();
$end = $rfn->getEndLine();
if(!is_readable($file)) return ''; # file should be readable
# cache file contents for subsequent reads (in case we use multiple fns defined in the same file)
$md5 = md5($file);
if(!isset($contents_cache[$md5]))
$contents_cache[$md5] = file($file, FILE_IGNORE_NEW_LINES);
if(empty($contents_cache[$md5])) return ''; # there should be stuff in the file
$file = $contents_cache[$md5];
# get function code and tokens
$code = "<?php ". implode($nl, array_slice($file, $start-1, ($end+1)-$start));
$tokens = token_get_all( $code);
# now let's parse the code;
$code = '';
$function_count = 0;
$ignore_input = false; # we use this to get rid of "use" or function name
$got_header = false;
$in_function = false;
$braces_level = 0;
foreach($tokens as $token){
# get the token name or string
if(is_string($token)){
$token_name = $token;
}elseif(is_array($token) && isset($token[0]) ){
$token_name = token_name($token[0]);
$token = isset($token[1]) ? $token[1] : "";
}else{
continue;
}
# strip comments
if( 1
&& $strip_comments
&& ($token_name == "T_COMMENT" || $token_name == "T_DOC_COMMENT" || $token_name == "T_ML_COMMENT")
){
# but put back the new line
if(substr($token,-1) == "\n")
$code.=$nl;
continue;
}
# let's decide what to do with it now
if($in_function){
# nesting level
if($token_name == "{"){
$braces_level++;
# done ignoring `use`
$ignore_input = false;
}
# append
if( 1
&& $function_count==1
&& ( 0
# skip function names
|| ( $ignore_input && $token_name == "(" && !$got_header && (!($ignore_input=false)) )
# skip function () use (...) in closures functions
|| ( $braces_level == 0 && !$got_header && $token_name == ")" && ($ignore_input=true) && ($got_header=true) )
# this fall-through is intentional
|| !$ignore_input
)
) {
$code .= $token;
}
# ending "}"
if($token_name == "}"){
$braces_level--;
# done collecting the function
if($braces_level == 0)
$in_function = false;
}
}elseif($token_name == "T_FUNCTION"){
$function_count++;
$in_function = true;
$ignore_input = true;
$braces_level = 0;
$code.=$token;
# we can't detect this properly so bail out
if($function_count>1){
$code = '';
break;
}
}
}
return $code;
}
该函数使用ReflectionFunction类来确定声明传递函数的位置,并使用token_get_all()来处理声明的不同部分。
这可以按预期工作:
然而,
function a(){} function b(){} fn_to_string('a'); // fails
use
关键字以避免将来出现问题我正在努力确定这样的事情是否适合现实世界。所以我的问题是:
is_readable(__FILE__)===false