Andrew
Andrew

Reputation: 239087

Call function dynamically, regardless of being instance method or static?

I need to be able to call a method without having to know whether or not it is static.

For example, this doesn't work and I would like it to:

class Groups {
    public function fetchAll($arg1, $arg2){
        return $this->otherFunction();
    }
    public static function alsoFetchAll($arg1, $arg2){}
}

$arguments = array('one', 'two');
$result = call_user_func_array(array('Groups', 'fetchAll'), $arguments);
$result = call_user_func_array(array('Groups', 'alsoFetchAll'), $arguments);

I'm getting an error for the instance varirable:

Fatal error: Using $this when not in object context

The reason it doesn't work is because I need to instantiate the class for the instance variables to work. But my constructor doesn't take any arguments so I want a quick way to skip this step.

How can I write this so that it doesn't matter what kind of method it is?

Upvotes: 1

Views: 184

Answers (2)

nickb
nickb

Reputation: 59709

You can do this with Reflection. Assuming you have these variables:

$class = 'Groups';
$params = array(1, 'two');

Then you can create a new instance of the class:

$ref = new ReflectionClass( $class);
$instance = $ref->newInstance();

And call both methods the same way, checking if they're static or not for completeness:

$method = $ref->getMethod( 'fetchAll');
$method->invokeArgs( ($method->isStatic() ? null : $instance), $params);

$method = $ref->getMethod( 'alsoFetchAll');
$method->invokeArgs( ($method->isStatic() ? null : $instance), $params);

However, you don't need to make sure they're static, you can just as easily do this, regardless of whether or not the method is static:

$ref->getMethod( 'fetchAll')->invokeArgs( $instance, $params);
$ref->getMethod( 'alsoFetchAll')->invokeArgs( $instance, $params);

You can see it working in this demo.

Edit: Here is a demo showing that this works with the OP's use case, without any errors / warnings / notices.

Upvotes: 2

moonwave99
moonwave99

Reputation: 22820

I think there is a design problem - if you need an instance method, you need an instance, so probably you need to access that instance's properties.

If you need a static method, you don't need to reference any instance, so go with call_user_func_array. As you are dealing with repository method, you can make them static without any problem - anyway if you need a solution:

function callMethod($class, $method, $arguments)
{

    // if there is no such method, return
    $info = new ReflectionClass($class);
    if(!$info -> hasMethod($method))
        return false;

    // let's find if desired method is static - create a temporary instance in case
    foreach($info -> getMethods(ReflectionMethod::IS_STATIC) as $method)
    {

        if($method['name'] == $method)
        {

            $class = $info -> newInstance;
            break;

        }

    }

    return call_user_func_array(array($class, $method), $arguments);

}

Upvotes: 1

Related Questions