Dynamically Invoking Class Method Args
Asked Answered
B

3

7

I am working on something where I need to be able to pass an indexed array of args to a method, much like how call_user_func_array works. I would use call_user_func_array but it is not an OOP approach, which is undesired, and it requires the method to be static, which breaks the target class's OO.

I have tried to use ReflectionClass but to no avail. You cannot invoke arguments to a method of the class, only the constructor. This is unfortunately, not desireable.

So I took to the man pages and looked at ReflectionFunction but there is no way to instantiate the class, point it to a method, and then invokeArgs with it.

Example using ReflectionFunction ( remember, this question is tagged PHP 5.4, hence the syntax):

$call = new \ReflectionFunction( "(ExampleClass())->exampleMethod" );
$call->invokeArgs( ["argument1", "argument2"] );

This fails with:

Function (Index())->Index() does not exist

Example using ReflectionMethod

$call = new \ReflectionMethod( "ExampleClass", "exampleMethod" );
$call->invokeArgs( new ExampleClass(), ["argument1", "argument2"] );
print_r( $call );

This fails with:

ReflectionMethod Object
(
    [name] => Index
    [class] => Index
)

The arguments are never passed to the method.

The desired results are:

class ExampleClass() {
    public function exampleMethod( $exampleArg1, $exampleArg2 ){
        // do something here
        echo "Argument 1: {$exampleArg1}\n";
        echo "Argument 2: {$exampleArg2}\n";
    }
}

$array = [ 'exampleArg1Value', 'exampleArg2Value' ];

If I passed $array to an instance of ExampleClass->exampleMethod(), I would only have one argument, which would be an array. Instead, I need to be able to pull the individual arguments.

I was thinking that if there was a way to call ReflectorFunction on a ReflectorClass I would in in ship-shape and on my way, but it doesn't look like that is possible.

Does anyone have anything they have used to accomplish this previously?

Backslide answered 27/9, 2012 at 19:57 Comment(0)
B
4

For some reason, something got stuck, somewhere.

$call = new \ReflectionMethod( "ExampleClass", "exampleMethod" );
$call->invokeArgs( new ExampleClass(), ["argument1", "argument2"] );

Now returns

Argument 1: argument1
Argument 2: argument2

I am going to try to reproduce the issue. It is on a fresh php 5.4.7 install with php-cli and fpm.

Backslide answered 28/9, 2012 at 13:49 Comment(1)
Yes it should just work, you can easily check against PHP versions here: 3v4l.org/JUKK9#v547 - Take care that your class is not from some other namespace or something.Trujillo
M
6

AFAIK, the following should work:

$call = new \ReflectionMethod( "ExampleClass", "exampleMethod" );
$call->invokeArgs( new ExampleClass(), ["argument1", "argument2"] );
print_r( $call );

What minor version is PHP? Are you on 5.4.7?

Margerymarget answered 27/9, 2012 at 19:58 Comment(0)
B
4

For some reason, something got stuck, somewhere.

$call = new \ReflectionMethod( "ExampleClass", "exampleMethod" );
$call->invokeArgs( new ExampleClass(), ["argument1", "argument2"] );

Now returns

Argument 1: argument1
Argument 2: argument2

I am going to try to reproduce the issue. It is on a fresh php 5.4.7 install with php-cli and fpm.

Backslide answered 28/9, 2012 at 13:49 Comment(1)
Yes it should just work, you can easily check against PHP versions here: 3v4l.org/JUKK9#v547 - Take care that your class is not from some other namespace or something.Trujillo
G
3

I have written my own dependency injector, and I also construct classes with the parameters dynamicly. Here is some code that should get your going:

$type = 'ExampleClass';

$reflector = new \ReflectionClass( $type );

if ( !$reflector->isInstantiable() )
  throw new \Exception( "Resolution target [$type] is not instantiable." );

$constructor = $reflector->getConstructor();

$parameters = $constructor->getParameters();

At this point you have a array of parameters, needed for construction. You can now substitute the parameters with the values and construct the class.

Gasperoni answered 27/9, 2012 at 20:24 Comment(1)
Thanks! Im looking more towards invoking a method rather than constructing a class. Im going to play around with what you gave and let you know.Backslide

© 2022 - 2024 — McMap. All rights reserved.