3

I'm trying to create functions dynamically with eval(). But I get this warning: Notice: Use of undefined constant Any suggestion?

$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 />';
}

Assuming the array $func is an option value stored in a database and I need the function names for a callback function in a separate part of the script. So creating anonymous functions with create_function() is not what I'm looking for.

Thanks for your info.

11
  • 4
    In the line mainfunc(' . $func_name . ');, you need to wrap $func_name in quotes. As it stands now, that line turns to mainfunc(func_a);. Commented Sep 19, 2012 at 6:01
  • 6
    This seems like a pretty bad idea overall. Just saying. Commented Sep 19, 2012 at 6:02
  • 1
    take a look over here also; stackoverflow.com/questions/12438521/… Commented Sep 19, 2012 at 6:05
  • I don't think it's necessary to create function dynamically in such case. Commented Sep 19, 2012 at 6:08
  • To those who don't see the necessity of it, there are cases which need to pass function names to a custom function which expects a function name in the parameter as a call-back function, like add_action() in WordPress. When creating action hooks to schedule background processes in WordPress based on unique Ids, creating dynamic functions based on the saved ID becomes useful. Hope it makes sense. Commented Sep 19, 2012 at 6:16

3 Answers 3

4

Use better approach than eval(), it is called overloading.

Example:

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");

Output is:

_call(func_a)
_call(func_b)
_callStatic(func_a_static)
_callStatic(func_b_static)
Sign up to request clarification or add additional context in comments.

3 Comments

Interesting, thanks for your input. Just my PHP version does not support the callStack() method.
Then do not use __callStatic(). I have just demonstrated both possible solutions.
__call() seems to be the way to go. Thanks.
2

Your eval body needs to read:

mainfunc(\'' . $func_name . '\'); 

Without the single quotes, eval() makes code that has an unquoted literal--an undefined constant.

Comments

0

For those who were wondering what I was talking about, here is the sample WordPress plugin which demonstrates how dynamic function creation comes handy.

/* 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));
}

And the same functionality could be achieved with __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));
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.