下面是字符串:
<?php
$string = '//ps: this placeholder text to demonstrate issues..
function go($url) {
header("Location: {$url}");
exit();
}
function some() {
/* this is the function body */
$result = mysql_query("SELECT something FROM sometable");
while ($row = mysql_fetch_assoc($result)) {
//something...
}
return "something";
/* this is the function body */
}
function fetch2($result) {
while ($row = mysql_fetch_assoc($result)) {
//something...
}
return "something";
}';
?>
我已经尝试过正则表达式,它在某些情况下有效,而在其他情况下它没有(如果函数体内有大括号,我无法控制贪婪)。
这就是我的尝试:
preg_match('#function some\(\)\s*{(.+?)}#s', $string, $matches);
echo $match[1];
然而,由于在右大括号干扰匹配之前的一组大括号,这并没有给我完整的函数体。
我的问题(el):我怎样才能更可靠地获得功能体(当它们在闭合支架前支撑时没有麻烦)?有人建议使用token_get_all()
,但我不知道如何使用它或我应该使用它。
答案 0 :(得分:0)
您可以尝试这样的事情
$fragments = preg_split('/([\{\}])/', $string,0,PREG_SPLIT_DELIM_CAPTURE);
$functions = array();
$currentfunctionbody = '';
$currentnesting = 0;
$functionname = '';
for($i = 0; $i<count($fragments); $i++) {
$str = $fragments[$i];
/* New function ? */
preg_match("!function (.*?)\\(!", $str, $matches);
if(count($matches) > 0) {
$functionname = $matches[1]; }
/* Append to function body and deal with nesting */
else {
if(substr($str, 0,1) == '{') {
$currentnesting++; }
else if(substr($str, -1,1) == '}') {
$currentnesting--; }
$currentfunctionbody.=$str;
}
/* Close function */
if($currentfunctionbody != '' && $currentnesting == 0)
{
$functions[$functionname] = trim($currentfunctionbody,"{}");
$currentfunctionbody = '';
$functionname = '';
}
}
print_r($functions);
答案 1 :(得分:0)
这是另一种直接从文件中读取的替代解决方案:
$array = get_function_body('source.php', 'some');
print_r($array['body']);
function get_function_body($sourceFile, $functionName) {
$fd = fopen($sourceFile, "r");
while (!feof($fd)) {
$content = fgets($fd);
if ($content == "") {
continue;
}
if (isset($ret['args'])) {
if ($content == "//EOF")
break;
if (preg_match('/^\s*function\s+/', $content)) {
// EOFunction?
break;
}
$ret['body'] .= $content;
continue;
}
if (preg_match('/^\s*function\s+(.*)\s*\((.*)\)\s*\{\s*$/', $content, $resx)) {
if ($resx[1] == $functionName) {
$ret['args'] = $resx[2];
$ret['body'] = "";
}
}
}
fclose($fd);
return $ret;
}
答案 2 :(得分:0)
今天刚刚发生需要一个工具来检查源代码 PHP即时运行,并没有真正看到任何有趣的东西, 我把下面粘贴的类放在一起,使用了一些PHP的反射类。
它不仅可以即时为您提供PHP函数的源代码, 但它也会为您提供有关功能参数的详细信息(如果可用)
因此,如果您正在审讯的功能是这样的......
function nearby($lat=41.1663079,$lng=-113.8584736,$distance=150)
{
....
....
}
......除了函数的源代码之外,该类会给你详细介绍 像这样的领域信息......
Array( [lat] => Array( [position] => 0
[name] => lat
[type] => string
[default] => 41.1663079
[optional] => 1
[byreference] => 0 )
[lng] => Array( [position] => 1
[name] => lng
[type] => string
[default] => -113.8584736
[optional] => 1
[byreference] => 0 )
[distance] => Array( [position] => 2
[name] => distance
[type] => string
[default] => 150
[optional] => 1
[byreference] => 0 ) )
PHP的反射类没有很好地记录,(通常没有文档), 但是有足够的东西,今天有点烦躁,同样允许创作 下面的PHP“func_def”类。
我构建它是为了支持更大的努力,让我可以通过类型检查等实时安全地调用PHP函数。
享受!
实施例
$function_inspector =new func_def('whatever_function_name');
print "the function's source code is \n\n"
.$function_inspector->func_get_code() ;
print "the function's argument details are ".print_r($function_inspector->func_get_args());
/*
**
** The cool func_def class
** Scribbled up by :Dr. Clue
**
*/
class func_def extends ReflectionFunction
{//http://php.net/manual/en/class.reflectionfunctionabstract.php
protected $sz_fun_name =NULL ;
protected $bExists =FALSE ;
function __construct($func_name)
{
$this->sz_func_name=$func_name;
if(!function_exists($func_name))return;
try {parent::__construct($func_name); $this->bExists=TRUE;}
catch(Exception $e) {$this->bExists=FALSE; return; }
} // End Functon __constructor
function function_valid() { return $this->bExists==TRUE; }
function func_get_code()
{ // Returns Function's source code
if(!$this->bExists){return "/* function does not exist */";}
$line_start =$this->getStartLine() - 1;
$line_end =$this->getEndLine();
$line_count =$line_end - $line_start;
$line_array =file($this->getFileName());
return implode("", array_slice($line_array,$line_start,$line_count));
} // End Function
function func_get_args()
{ // Returns a fairly detailed descript of function arguments
$aParamerters=Array();
if(!$this->bExists)return $aParamerters;
foreach($Params=$this->getParameters() as $k=>$v)
{
$item= Array();
$s_export=array_pop($a=(array)$v->export($this->getName(),$v->getName(),TRUE) );
preg_match('/[^#]+[#]([0-9]+)/',$s_export,$m,PREG_OFFSET_CAPTURE);
$item["position"]=$m[1][0];$item["name" ]=$v->getName();$item["default" ]=$item["type" ]=NULL;
if(($item["optional"]=intVal($v->isOptional()) )==1)
if(preg_match('/[^[]+[^=]+=([^\]]+)/',$s_export,$m,PREG_OFFSET_CAPTURE))
{$item["default"]=($ev=trim($m[1][0]));$ev=("\$a=$ev;");eval($ev);$item["type"]=gettype($ev);}
if($item["type" ]==NULL)
if(preg_match('/[^[]+[\[][^>]+[> ]+([^&$]+)/',$s_export,$m,PREG_OFFSET_CAPTURE))$item["type"]=($ev=trim($m[1][0]));
$item["byreference"]=intVal(strpos($s_export,'&$')!==FALSE);
$aParamerters[$v->getName()]=$item;
}
return $aParamerters;
}
function func_num_args() {if(!$this->bExists)return FALSE;return $this->getNumberOfParameters() ;}
function func_num_args_required(){if(!$this->bExists)return FALSE;return $this->getNumberOfRequiredParameters();}
} // End Class