如何动态创建函数?

Ale*_*lex 13 php function

我有一个像变量 $string = "blah";

如何创建具有变量值作为名称的函数?这可能在PHP?

喜欢function $string($args){ ... }或类似的东西,并能称之为:

blah($args);
Run Code Online (Sandbox Code Playgroud)

far*_*jad 14

这可能不是一个好主意,但你可以这样做:

$string = "blah";
$args = "args"
$string = 'function ' . $string . "({$args}) { ... }";
eval($string);
Run Code Online (Sandbox Code Playgroud)

  • 没有!根本没有!:) (13认同)
  • 这应该是公认的答案.这是定义函数的唯一解决方案,而不是闭包.尝试`get_defined_functions()['user']`和`get_defined_vars()`来看看差异. (5认同)
  • 哦,来吧,这是问题的最佳答案.如果你明智地使用它,使用`eval`也不错.如果它是如此糟糕,为什么最受尊敬的脚本语言支持它?假设语言解释器将为"eval"分叉另一个解释器进程是荒谬的; 如果是这样的话,语言是完全有缺陷的.通常通过进程'`stdin`运行文本来完成`eval` - 正如代码的其余部分一样. (3认同)

Ric*_*ohn 11

这听起来不是一个伟大的设计选择,可能值得重新考虑,但......

如果您使用的是PHP 5.3,则可以使用匿名函数.

<?php
$functionName = "doStuff";
$$functionName = function($args) {
    // Do stuff
};

$args = array();
$doStuff($args);
?>
Run Code Online (Sandbox Code Playgroud)

  • 从技术上讲,这不是定义一个函数,而是一个闭包.尝试`get_defined_functions()['user']`和`get_defined_vars()`来看看差异. (2认同)

dke*_*ner 6

好的,接受挑战!

不管这个问题有多古怪(不是顺便说一句),让我们认真考虑一下!拥有一个可以声明函数并使它们真实的类可能会很有用:

<?php

customFunctions::add("hello",                 // prepare function "hello"

    function($what) {
        print "Hello $what, as Ritchie said";
        print "<br>";
    }

);

customFunctions::add("goodbye",               // prepare function "goodbye"

    function($what,$when) {
        print "Goodbye cruel $what, ";
        print "I'm leaving you $when";
        print "<br>";
    }

);

eval(customFunctions::make());                // inevitable - but it's safe!
Run Code Online (Sandbox Code Playgroud)

而已!现在它们是真正的功能。无需$前缀,只要调用它们就无需运行时评估-只需声明一次 eval()即可。之后,它们就像任何功能一样工作。

让我们尝试一下:

    hello('World');                 // "Hello World"
    goodbye('world','today');       // "Goodbye cruel world, I'm leaving you today" 
Run Code Online (Sandbox Code Playgroud)

魔术背后

这是可以做到这一点的班级。真的不复杂:

class customFunctions {

    private static $store = [];
    private static $maker = "";
    private static $declaration = '
        function %s() {
            return call_user_func_array(
                %s::get(__FUNCTION__),
                func_get_args()
            );
        }
    ';

    private static function safeName($name) {
        // extra safety against bad function names
        $name = preg_replace('/[^a-zA-Z0-9_]/',"",$name);
        $name = substr($name,0,64);
        return $name;
    }

    public static function add($name,$func) {
        // prepares a new function for make()
        $name = self::safeName($name);
        self::$store[$name] = $func;
        self::$maker.=sprintf(self::$declaration,$name,__CLASS__);
    }

    public static function get($name) {  
        // returns a stored callable
        return self::$store[$name];
    }

    public static function make() {  
        // returns a string with all declarations
        return self::$maker;
    }

}
Run Code Online (Sandbox Code Playgroud)

它为您的函数提供内部存储,然后声明调用它们的“真实”函数。这与fardjad的解决方案类似,但是具有实际代码(而非字符串),因此更加方便和可读。