tags:

views:

73

answers:

3

I'm not quite sure how to correctly put this question. I want to dynamically call functions that are contained in classes (I think this means they are called 'methods').

Here is an example of my code which I hope helps explain what I am trying to achieve.

In this instance $result returns all the different modules that are loaded. This then checks if the module's PHP file has been included with it's class, then if that class exists - trys to call the class directly.

foreach ($results as $result) {
    $moduleclass_name = 'TestClassName_' . $result->module_name . '::FunctionToCall';
    if (method_exists($moduleclass_name, 'FunctionToCall'))
        $VariableToRetrieve = $modulefunction_name($Parameter1, $Parameter2);
}

This returns an error

"Call to undefined function TestClassName_modulename::FunctionToCall()"

although the 'TestClassName' has been declared correctly.

Can someone tell me what I'm doing wrong?

+3  A: 

What you want is probably call_user_func_array().

The code would look similar to this:

call_user_func_array(array($classNameOrInstance, $functionName), array($arg1, $arg2, $arg3));

EDIT Also, in your example you seem to have included the function name in the class parameter for method_exists, too...

Franz
A: 

You may use call_user_func() as such to achieve what you are trying to do. Also, it is better to use is_callable() instead of method_exists() to validate if the method is callable (method may exist but its visibility may prevent it from being callable.

foreach ($results as $result) {
    $module_callback = array('TestClassName_' . $result->module_name,'FunctionToCall');
    if (is_callable($module_callback))
        $VariableToRetrieve = call_user_func($module_callback, $Parameter1, $Parameter2);
}
Andrew Moore
A: 

Hello,

  1. I think it doesn't work because your syntax may not support "static method calls". I suggest you give a try to Franz's method call_user_func().

  2. I did a similar thing on a former project.

It was designed to call a class which implemented an interface, so method names where known. I don't think it's difficult to modify this code in order to make it match with yours.

class CDispatcher {
    public static function GetDispatcher( $module = 'core' ) {
        $class_name = $module . 'Dispatcher';

        try {
            // looks for the file associated with the class
            // if the file is not found an exception is raised
            search_class( $class_name );
        } catch ( exception $e ){
            throw new UnkwownModuleException($module);
        }

        return new $class_name();
    }
}

// Then, you call this class :
$new_instance = CDispatcher::GetDispatcher( $my_module );
Arno