【发布时间】:2011-01-12 23:04:08
【问题描述】:
如何获取在 php 文件中声明的函数列表
【问题讨论】:
如何获取在 php 文件中声明的函数列表
【问题讨论】:
您可以使用get_defined_functions()获取当前定义的函数列表:
$arr = get_defined_functions();
var_dump($arr['user']);
内部函数位于索引internal,而用户定义函数位于索引user。
请注意,这将输出在该调用之前声明的所有函数。这意味着如果您 include() 带有函数的文件,这些文件也会在列表中。除了确保在调用get_defined_functions() 之前没有include() 任何文件之外,没有办法分离每个文件的函数。
如果您必须拥有每个文件的函数列表,则以下将尝试通过解析源来检索函数列表。
function get_defined_functions_in_file($file) {
$source = file_get_contents($file);
$tokens = token_get_all($source);
$functions = array();
$nextStringIsFunc = false;
$inClass = false;
$bracesCount = 0;
foreach($tokens as $token) {
switch($token[0]) {
case T_CLASS:
$inClass = true;
break;
case T_FUNCTION:
if(!$inClass) $nextStringIsFunc = true;
break;
case T_STRING:
if($nextStringIsFunc) {
$nextStringIsFunc = false;
$functions[] = $token[1];
}
break;
// Anonymous functions
case '(':
case ';':
$nextStringIsFunc = false;
break;
// Exclude Classes
case '{':
if($inClass) $bracesCount++;
break;
case '}':
if($inClass) {
$bracesCount--;
if($bracesCount === 0) $inClass = false;
}
break;
}
}
return $functions;
}
使用风险自负。
【讨论】:
T_CURLY_OPEN添加到开关中以捕获"hello {$name}"等字符串
您可以在包含文件之前和之后使用 get_defined_functions(),然后查看第二次添加到数组中的内容。由于它们似乎是按定义顺序排列的,因此您可以像这样使用索引:
$functions = get_defined_functions();
$last_index = array_pop(array_keys($functions['user']));
// Include your file here.
$functions = get_defined_functions();
$new_functions = array_slice($functions['user'], $last_index);
【讨论】:
您可以使用get_defined_functions() 函数来获取当前脚本中定义的所有函数。
见:http://www.php.net/manual/en/function.get-defined-functions.php
如果你想获取另一个文件中定义的函数,你可以尝试像这样使用http://www.php.net/token_get_all:
$arr = token_get_all(file_get_contents('anotherfile.php'));
然后您可以循环查找已定义符号的函数标记。令牌列表可以找到http://www.php.net/manual/en/tokens.php
【讨论】:
token_get_all()。如果你使用includes和requires,其他文件中定义的函数也会在这个文件中定义。
如果您不担心发现一些被注释掉的,这可能是最简单的方法:
preg_match_all('/function (\w+)/', file_get_contents(__FILE__), $m);
var_dump($m[1]);
【讨论】:
我写了这个小函数来返回文件中的函数。
https://gist.github.com/tonylegrone/8742453
它返回一个包含所有函数名的简单数组。如果您在要扫描的特定文件中调用它,您可以使用以下内容:
$functions = get_functions_in_file(__FILE__);
【讨论】:
我用array_diff解决了这个问题
$funcs = get_defined_functions()["user"];
require_once 'myFileWithNewFunctions.php'; // define function testFunc() {} here
var_dump( array_values( array_diff(get_defined_functions()["user"], $funcs) ) )
// output: array[ 0 => "test_func"]
更新
要获得“真正的”函数名称,试试这个
foreach($funcsDiff AS $newFunc) {
$func = new \ReflectionFunction($newFunc);
echo $func->getName(); // testFunc
}
【讨论】:
好吧,如果你需要这样做,我会告诉你:
示例文件:Functions.php(我只是写了一些随机的东西并不能适用于所有东西)
<?php
// gewoon een ander php script. door het gebruiken van meerdere includes kun je gemakkelijk samen aan één app werken
function johannes($fnaam, $mode, $array){
switch ($mode) {
case 0:
echo "
<center>
<br><br><br><br><br>
he johannes!<br><br>
klik hier voor random text:<br>
<input type='submit' value='superknop' id='btn' action='randomding' level='0' loadloc='randomshit' />
<p id='randomshit'></p>
</center>
";
break;
case 1:
echo "bouw formulier";
break;
case 2:
echo "verwerk formulier";
break;
default:
echo "[Error: geen mode gedefinieerd voor functie '$fnaam'!]";
}
}
function randomding($fnaam, $mode, $array){
$randomar = array('He pipo wat mot je!','bhebhehehehe bheeeee. rara wie ben ik?','poep meloen!','He johannes, wat doeeeeee je? <input type="text" name="doen" class="deze" placeholder="Wat doe je?" /> <input type="button" value="vertellen!" id="btn" action="watdoetjho" level="0" loadloc="hierzo" kinderen="deze"> <p id="hierzo"></p>','knopje de popje opje mopje','abcdefghijklmnopqrstuvwxyz, doe ook nog mee','Appien is een **p!!!!!! hahhahah<br><br><br><br> hahaha','Ik weet eiegelijk niks meer te verzinnen','echt ik weet nu niks meer','nou oke dan[[][(!*($@#&*$*^éäåðßð','he kijk een microboat: <br> <img src="https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcS_n8FH6xzf24kEc31liZF6ULHCn2IINFurlFZ_G0f0_F4sLTi74w" alt="microboat" />');
$tellen = count($randomar);
$tellen--;
$rand = rand(0, $tellen);
echo $randomar[$rand];
}
function watdoetjho($fnaam, $mode, $array){
$dit = $array['doen'];
echo "Johannes is: $dit";
}
?>
我们这里有 3 个函数:
但我们也称这些函数为:
如果我们使用get_defined_functions,我们将获得脚本范围内的所有函数。是的,PHP 函数与用户声明的函数是分开的,但我们仍然希望来自特定文件。
如果我们使用token_get_all,我们会收到大量需要先分离的数据。
我找到了这些数字,我们需要在数组中建立一些连接以匹配用户函数。否则,我们将得到一个列表,其中包含所有调用的 php 函数。
数字是:
如果我们过滤数组以获取所有 334 个元素,我们有这样的:
334 -|- 函数 -|- 5
但是我们需要函数名,并且所有数组元素都与第三个值相关。所以现在我们需要过滤所有匹配第三个值(5)和常数307的数组元素。
这会给我们这样的东西:
307 -|- 约翰内斯 -|- 5
现在在 PHP 中它看起来像这样:
<?php
error_reporting(E_ALL ^ E_NOTICE); // Or we get these undefined index errors otherwise use other method to search array
// Get the file and get all PHP language tokens out of it
$arr = token_get_all(file_get_contents('Functions.php'));
//var_dump($arr); // Take a look if you want
//The array where we will store our functions
$functions = array();
// loop trough
foreach($arr as $key => $value){
//filter all user declared functions
if($value[0] == 334){
//Take a look for debug sake
//echo $value[0] .' -|- '. $value[1] . ' -|- ' . $value[2] . '<br>';
//store third value to get relation
$chekid = $value[2];
}
//now list functions user declared (note: The last check is to ensure we only get the first peace of information about the function which is the function name, else we also list other function header information like preset values)
if($value[2] == $chekid && $value[0] == 307 && $value[2] != $old){
// just to see what happens
echo $value[0] .' -|- '. $value[1] . ' -|- ' . $value[2] . '<br>';
$functions[] = $value[1];
$old = $chekid;
}
}
?>
这种情况下的结果是:
307 -|- johannes -|- 5
307 -|- randomding -|- 31
307 -|- watdoetjho -|- 43
【讨论】:
要获取代码中已定义和使用的函数列表,通过小型有用的文件管理器,您可以使用下面的代码。享受吧!
if ((!function_exists('check_password'))||(!check_password()) ) exit('Access denied.'); //...security!
echo "<html><body>";
if (!$f) echo nl2br(htmlspecialchars('
Useful parameters:
$ext - allowed extensions, for example: ?ext=.php,css
$extI - case-insensitivity, for example: ?extI=1&ext=.php,css
'));
if (($f)&&(is_readable($_SERVER['DOCUMENT_ROOT'].$f))&&(is_file($_SERVER['DOCUMENT_ROOT'].$f))) {
echo "<h3>File <strong>$f</strong></h3>\n";
if(function_exists('get_used_functions_in_code')) {
echo '<h3>Used:</h3>';
$is=get_used_functions_in_code(file_get_contents($_SERVER['DOCUMENT_ROOT'].$f));
sort($is);
$def=get_defined_functions();
$def['internal']=array_merge($def['internal'], array('__halt_compiler', 'abstract', 'and', 'array', 'as', 'break', 'callable', 'case', 'catch', 'class', 'clone', 'const', 'continue', 'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', 'exit', 'extends', 'final', 'finally', 'for', 'foreach', 'function', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'interface', 'isset', 'list', 'namespace', 'new', 'or', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'return', 'static', 'switch', 'throw', 'trait', 'try', 'unset', 'use', 'var', 'while'));
foreach ($def['user'] as &$e) $e=strtolower($e); unset($e);
foreach ($is as &$e) if (!in_array(strtolower($e), $def['internal'], TRUE)) $e='<span style="color: red">'.$e.'</span>'; unset($e); //user-defined functions will be red
echo implode('<br />'.PHP_EOL,$is);
}
else echo "Error: missing function 'get_used_functions_in_code' !";
if(function_exists('get_defined_functions_in_code')) {
echo '<br /><h3>Defined:</h3>';
$is=get_defined_functions_in_code(file_get_contents($_SERVER['DOCUMENT_ROOT'].$f));
sort($is);
echo implode('<br />',$is);
}
else echo "Error: missing function 'get_defined_functions_in_code' !";
}
/*
File manager
*/
else {
if (!function_exists('select_icon')) {
function select_icon($name) {$name = pathinfo($name); return '['.$name["extension"].']';}
}
if($ext) $extensions=explode(',',strrev($ext));
if(!$f) $f=dirname($_SERVER['PHP_SELF']);
echo "<h3>Dir ".htmlspecialchars($f)."</h3><br />\n<table>";
$name=scandir($_SERVER['DOCUMENT_ROOT'].$f);
foreach($name as $name) {
if (!($fileOK=(!isset($extensions)))) {
foreach($extensions as $is) if (!$fileOK) $fileOK=((strpos(strrev($name),$is)===0)||($extI &&(stripos(strrev($name),$is)===0)));
}
$is=is_dir($fullName=$_SERVER['DOCUMENT_ROOT']."$f/$name");
if ($is || $fileOK) echo '<tr><td>'.select_icon($is ? 'x.folder' : $name).' </td><td> '.($is ? '[' : '').'<a href="?f='.rawurlencode("$f/$name").($extI ? "&extI=$extI" : '').($ext ? "&ext=$ext" : '').'">'.htmlspecialchars($name).'</a>'.($is ? ']' : '').'</td>';
if ($is) echo '<td> </td><td> </td>';
elseif ($fileOK) echo '<td style="text-align: right"> '.number_format(filesize($fullName),0,"."," ").' </td><td> '.date ("Y.m.d (D) H:i",filemtime($fullName)).'</td>';
if ($is || $fileOK) echo '</tr>'.PHP_EOL;
}
echo "\n</table>\n";
}
echo "<br /><br />".date ("Y.m.d (D) H:i")."</body></html>";
return;
/********************************************************************/
function get_used_functions_in_code($source) {
$tokens = token_get_all($source);
$functions = array();
$thisStringIsFunc = 0;
foreach($tokens as $token) {
if(($token[0]!=T_WHITESPACE)&&((!is_string($token))||($token[0]!='('))) unset($func);
if((is_array($token))&&(in_array($token[0],array(T_EVAL,T_EXIT,T_INCLUDE,T_INCLUDE_ONCE,T_LIST,T_REQUIRE,T_REQUIRE_ONCE,T_RETURN,T_UNSET)))) {$token[0]=T_STRING;$thisStringIsFunc=1;}
switch($token[0]) {
case T_FUNCTION: $thisStringIsFunc=-1;
break;
case T_STRING:
if($thisStringIsFunc>0) {
if (!in_array(strtoupper($token[1]),$functionsUp)) {$functions[]=$token[1];$functionsUp[]=strtoupper($token[1]);}
$thisStringIsFunc = 0;
} elseif ($thisStringIsFunc+1>0) {
$func = $token[1];
} else $thisStringIsFunc = 0;
break;
case '(':if($func) if(!in_array(strtoupper($func),$functionsUp)) {$functions[]=$func;$functionsUp[]=strtoupper($func);}
}
}
return $functions;
}
/********************************************/
function get_defined_functions_in_code($source) {
$tokens = token_get_all($source);
... then Andrew code (get_defined_functions_in_file) (https://stackoverflow.com/a/2197870/9996503)
}
【讨论】:
使用正则表达式在文件中查找字符串(例如函数名称)很简单。
只需读取文件并使用 preg_match_all 解析内容即可。
我写了一个简单的函数来获取文件中的函数列表。
https://gist.github.com/komputronika/f92397b4f60870131ef52930faf09983
$a = functions_in_file( "mylib.php" );
【讨论】:
最简单的事情(在我看到@joachim 的回答之后)是使用get_defined_functions,然后只注意“用户”键(其中包含一组用户定义的方法)
这是帮助我解决问题的代码
<?php
//Just to be sure it's empty (as it should be)
$functions = get_defined_functions();
print_r($functions['user']);
//Load the needed file
require_once '/path/to/your/file.php';
//display the functions loaded
$functions2 = get_defined_functions();
print_r($functions2['user']);
【讨论】:
还要检索参数定义:(Source in comments)
数组
(
[0] => function foo ( &&bar, &big, [$small = 1] )
[1] => function bar ( &foo )
[2] => function noparams ( )
[3] => function byrefandopt ( [&$the = one] )
)
$functions = get_defined_functions();
$functions_list = array();
foreach ($functions['user'] as $func) {
$f = new ReflectionFunction($func);
$args = array();
foreach ($f->getParameters() as $param) {
$tmparg = '';
if ($param->isPassedByReference()) $tmparg = '&';
if ($param->isOptional()) {
$tmparg = '[' . $tmparg . '$' . $param->getName() . ' = ' . $param->getDefaultValue() . ']';
} else {
$tmparg.= '&' . $param->getName();
}
$args[] = $tmparg;
unset ($tmparg);
}
$functions_list[] = 'function ' . $func . ' ( ' . implode(', ', $args) . ' )' . PHP_EOL;
}
print_r($functions_list);
【讨论】:
在文件中包含并试试这个:
$functions = get_defined_functions();
print_r($functions['user']);
【讨论】: