Как я могу создать функцию динамически? - PullRequest
12 голосов
/ 18 декабря 2011

У меня есть переменная типа $string = "blah";

Как я могу создать функцию, которая имеет значение переменной в качестве имени? Возможно ли это в PHP?

Как function $string($args){ ... } или что-то еще, и можно назвать это как:

blah($args);

Ответы [ 5 ]

14 голосов
/ 18 декабря 2011

это может быть не очень хорошая идея, но вы можете сделать что-то вроде этого:

$string = "blah";
$args = "args"
$string = 'function ' . $string . "({$args}) { ... }";
eval($string);
11 голосов
/ 18 декабря 2011

Это не похоже на отличный выбор дизайна, возможно, стоит переосмыслить его, но ...

Если вы используете PHP 5.3, вы можете использовать анонимную функцию.

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

$args = array();
$doStuff($args);
?>
4 голосов
/ 12 июля 2018

Хорошо, вызов принят!

Неважно, насколько странный вопрос (это, кстати, не так), давайте на минутку отнесемся к нему серьезно! Может быть полезно иметь класс, который может объявить функции и сделать их реальными:

<?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!

Вот и все! Теперь они настоящие функции. Без префикса $, без оценки времени выполнения при вызове - eval () требовался только один раз для объявления. После этого они работают как любая функция.

Давайте попробуем их:

    hello('World');                 // "Hello World"
    goodbye('world','today');       // "Goodbye cruel world, I'm leaving you today" 

Магия позади

Вот класс, который может это сделать. На самом деле не сложный:

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;
    }

}

Он предоставляет внутреннее хранилище для ваших функций, а затем объявляет «настоящие» функции, которые их вызывают. Это что-то похожее на решение fardjad , но с реальным кодом (не строками) и поэтому намного удобнее и удобочитаемее.

1 голос
/ 18 декабря 2011

Попробуйте call_user_func_array()

php.net ссылка

1 голос
/ 18 декабря 2011

Вы можете вызывать функцию по ее имени, хранящемуся в переменной, а также можете назначать функцию переменным и вызывать ее с помощью переменной.Если это не то, что вы хотите, пожалуйста, объясните больше.

...