在PHP中使用eval()动态创建函数

3

我正在尝试使用 eval() 动态创建函数。但是我收到了以下警告:注意:使用未定义的常量。有什么建议吗?

$funcs = array('func_a', 'func_b', 'func_c');
foreach($funcs as $func_name) {
    eval( 'function ' . $func_name . '() { 
            mainfunc(' . $func_name . '); 
        }' 
    );  
}

func_a();
func_b();
func_c();

function mainfunc($func_name) {
    echo $func_name . '<br />';
}

假设数组$func是存储在数据库中的选项值,并且我需要在脚本的另一部分中获取用于回调函数的函数名称。因此,使用create_function()创建匿名函数并不是我所需求的。
感谢您的信息。

4
在这行代码 mainfunc(' . $func_name . '); 中,你需要在 $func_name 周围加上引号。现在的情况是,这一行变成了 mainfunc(func_a); - DCoder
6
整体而言,这似乎是一个相当糟糕的想法。只是说一下。 - deceze
1
请看这里:http://stackoverflow.com/questions/12438521/call-a-function-without-knowing-its-name/ - Tom
我认为在这种情况下动态创建函数是不必要的。 - xdazz
我对WordPress没有太多经验,但我知道至少有一些东西在WordPress中接受的不仅仅是纯字符串。也就是说,PHP中的任何有效回调都应该可以工作,例如array($obj, 'method')。此外,如果您使用create_function,这也将起作用,因为它创建了一个具有随机名称的实际函数,您可以传递其名称! - deceze
显示剩余6条评论
3个回答

4

请使用比eval()更好的方法,这就是所谓的重载

例如:

class MainFunc {

    public function __call($name, $arguments)
    {
        echo "_call($name)<br>";
    }

    public static function __callStatic($name, $arguments)
    {
        echo "_callStatic($name)<br>";
    }

}

# php >= 5.4.x
(new MainFunc)->func_a();
(new MainFunc)->func_b("param", "param2");
# or php < 5.4
$mainFunc = new MainFunc;
$mainFunc->func_a();
$mainFunc->func_b("param", "param2");

MainFunc::func_a_static();
MainFunc::func_b_static("param", "param2");

输出结果为:

_call(func_a)
_call(func_b)
_callStatic(func_a_static)
_callStatic(func_b_static)

有趣,感谢您的输入。只是我的PHP版本不支持callStack()方法。 - Teno
那么就不要使用__callStatic()。我刚刚演示了两种可能的解决方案。 - Glavić
__call() 似乎是正确的方法。谢谢。 - Teno

2
您的eval函数体需要读取以下内容:
mainfunc(\'' . $func_name . '\'); 

没有单引号,eval()会生成一个没有引号的文本--一个未定义的常量。

0

对于那些想知道我在说什么的人,这是一个示例WordPress插件,演示了动态函数创建的实用性。

/* Plugin Name: Sample Action Hooks with Dynamic Functions */

// assuming this is an option retrieved from the database
$oActions = array(  'a' => array('interval' => 10, 'value' => 'hi'),
                    'b' => array('interval' => 30, 'value' => 'hello'),
                    'c' => array('interval' => 60, 'value' => 'bye')
            );  

add_action('init', LoadEvents);
function LoadEvents() {
    global $oActions;
    foreach($oActions as $strActionName => $array) {
        eval( 'function ' . $strActionName . '() { 
                    SampleEvents(\'' . $strActionName . '\'); 
                }' 
        );  
        add_action('sampletask_' . md5($strActionName), $strActionName);
        if (!wp_next_scheduled( 'sampletask_' . md5($strActionName)))
            wp_schedule_single_event(time() + $oActions[$strActionName]['interval'], 'sampletask_' . md5($strActionName));                  
    }
}
function SampleEvents($strActionName) {
    global $oActions;
    // just log for a demo
    $file = __DIR__ . '/log.html';
    $current = date('l jS \of F Y h:i:s A') . ': ' . $strActionName . ', ' . $oActions[$strActionName]['value'] . '<br />' . PHP_EOL;
    file_put_contents($file, $current, FILE_APPEND);    
    wp_schedule_single_event(time() + $oActions[$strActionName]['interval'], 'sampletask_' . md5($strActionName));
}

同样的功能也可以通过使用__call()来实现。

/* Plugin Name: Sample Action Hooks */

add_action('init', create_function( '', '$oSampleEvents = new SampleEvents;' ));
class SampleEvents {
    public $oActions = array(   'a' => array('interval' => 10, 'value' => 'hi'),
                                'b' => array('interval' => 30, 'value' => 'hello'),
                                'c' => array('interval' => 60, 'value' => 'bye')
                        );
    function __construct() {                
        foreach($this->oActions as $strActionName => $arrAction) {
            add_action('sampletask_' . md5($strActionName), array(&$this, $strActionName));
            if (!wp_next_scheduled( 'sampletask_' . md5($strActionName)))
                wp_schedule_single_event(time() + $this->oActions[$strActionName]['interval'], 'sampletask_' . md5($strActionName));
        }
    }
    function __call($strMethodName, $arguments) {
        // just log for a demo
        $file = __DIR__ . '/log.html';
        $current = date('l jS \of F Y h:i:s A') . ': ' . $strMethodName . ', ' . $this->oActions[$strMethodName]['value'] . '<br />' . PHP_EOL;
        file_put_contents($file, $current, FILE_APPEND);    
        wp_schedule_single_event(time() + $this->oActions[$strMethodName]['interval'], 'sampletask_' . md5($strMethodName));
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接