我正在尝试找到一种方法来获取字符串中(用户定义的)PHP函数的源代码。
对于普通代码,这很容易,使用反射我可以找到定义函数的文件和行号;然后我可以打开文件并阅读函数源代码。
如果在eval'd代码中定义了函数,则无效。我不想记录所有评估的代码。
这可能吗?如果是,那怎么办?
示例代码:
function myfunction() {
echo "Test";
}
eval('
function myevalfunction() {
echo "Test";
}
');
$a = new ReflectionFunction('myfunction');
echo $a;
$b = new ReflectionFunction('myevalfunction');
echo $b;
输出:
Function [ <user> <visibility error> function myfunction ] {
@@ test.php 3 - 5
}
Function [ <user> <visibility error> function myevalfunction ] {
@@ test.php(11) : eval()'d code 2 - 4
}
答案 0 :(得分:1)
我最初的回答是说在eval中创建函数几乎没有理由。
您可以有条件地创建函数,即:
if ( $cond ){
function foo(){
}
}
如果你想要闭合这样的行为,我猜eval是唯一的方法,直到PHP5.3,但它的 EPIC 坏东西,你应该避免所有成本。
原因如下:
01 <?php 02 03 function foo () 04 { 05 eval( ' 06 function baz() 07 { 08 eval("throw new Exception();"); 09 } 10 '); 11 baz(); 12 } 13 14 15 16 try{ 17 foo(); 18 }catch( Exception $e ){ 19 var_dump($e); 20 } 21 try{ 22 foo(); 23 } 24 catch( Exception $e ){ 25 var_dump($e); 26 }
发出这个:
object(Exception)#1 (6) { ["message:protected"]=> string(0) "" ["string:private"]=> string(0) "" ["code:protected"]=> int(0) ["file:protected"]=> string(50) "/tmp/xx.php(10) : eval()'d code(4) : eval()'d code" ["line:protected"]=> int(1) ["trace:private"]=> array(3) { [0]=> array(3) { ["file"]=> string(31) "/tmp/xx.php(10) : eval()'d code" ["line"]=> int(4) ["function"]=> string(4) "eval" } [1]=> array(4) { ["file"]=> string(11) "/tmp/xx.php" ["line"]=> int(11) ["function"]=> string(3) "baz" ["args"]=> array(0) { } } [2]=> array(4) { ["file"]=> string(11) "/tmp/xx.php" ["line"]=> int(17) ["function"]=> string(3) "foo" ["args"]=> array(0) { } } } } Fatal error: Cannot redeclare baz() (previously declared in /tmp/xx.php(10) : eval()'d code:2) in /tmp/xx.php(10) : eval()'d code on line 5 Call Stack: 0.0002 115672 1. {main}() /tmp/xx.php:0 0.0006 122304 2. foo() /tmp/xx.php:22
这么多的不好,很少的努力。
答案 1 :(得分:1)
你不能自己搜索文件? grep或wingrep是完美的。
如果没有,你可以尝试pecl函数rename_function并记录所有创建函数的eval调用。
答案 2 :(得分:1)
如何定义自己的eval-function,并在那里进行跟踪?
function myeval($code) {
my_eval_tracking($code, ...); # use traceback to get more info if necessary
# (...)
return eval($code);
}
那就是说,在这种情况下,我确实分享了很多Kent Fredric对eval的感受。
答案 3 :(得分:0)
如果您想找到源代码,即使在调试器中,您也可以定义自己的 eval() 函数来处理临时文件:
function my_eval($code) {
$file = << TEMP-DIR >> . '/' . md5($code) . '.php';
if (!file_exists($file)) {
$file = file_put_contents("<?php\n" . $code);
}
return require($file);
}
其实我觉得如果你调用这个函数eval
并将它放在默认的命名空间中,代码中的大多数eval()调用都会调用这个函数。