views:

54

answers:

2

Hey everyone,

I am using the __call magic within some of my mvc code to produce an autoloadable forms framework but I have ran into a problem I am hoping some one on here might have a work around for.

The __call magic takes two paramters: $methodName and $arguments. The arguments come back as an array of args which you called. Normally this function is called on methods you can do as such so feed these arguments into a function:

call_user_func_array($methodName, $arguments);

And this will propogate the methods signature with the arguments. I am trying to do something a little more complex. I am attempting to propogate a classes constructor the same way, through being able to send maybe a imploded comma deliminenated array of the arguments into the classes constructor or just sending the args in directly but both of these do not produce the required result. When I send an imploded array down into the constructor PHP thinks it's a string and when I send the array it thinks it's an array.

This is the code I am using atm:

public function __call($method, $args){

    return $this->init_element(new $method($args['name'], $args['value'], $args['opts']));

}

What if I had 4 arguments to pass down though? Is there a way I can get it to dynamically fill the constructor just like you can for a function using call_user_func_array()?

I could use an attributes() function to do this but I would really like to be able to do it like I can with functions.

Thanks in advance,

A: 

I saw the following somewhere around the web:

 call_user_func_array(array($obj, '__construct'), $args);
elusive
Could some one explain why this has been marked down since as far as I can tell this is not only the same speed (if not a little faster) than reflection and there does not appear to be any real security side effects from it. Could some one tell me why this has been marked down?
Sammaye
@Sammaye Wasn't me who downvoted, but I'd say it was dv'ed because it doesn't work. Calling `__construct` on an existing instance is pointless and providing the classname instead of `$obj` will produce a warning and no instance. If you want `call_user_func_array` give classes a static factory method and call that.
Gordon
Ah yea this might be good I'ma need to benchmark between the two.
Sammaye
I think that `$obj` is the name of that class. PHP typically handles invocation of class members like this. Example: `usort($someArray, array('SomeClass', 'someStaticSortFunc'))`.
elusive
A: 

Use PHP's reflection classes: (http://php.net/manual/en/class.reflectionclass.php)

$obj = new ReflectionClass( $classname );

then

$ins = $obj->newInstanceArgs( $arguments );

or

$ins = $obj->newInstance( );

Kolky
this solution is already given in the linked duplicate.
Gordon
woops, i did not notice that
Kolky
Whats the speed of this function? I know reflection can be very slow?
Sammaye
@Sammaye benchmark it in your app if you think it can make a significant slowdown
Gordon
As I get a test built up and that I saw this http://stackoverflow.com/questions/294582/php-5-reflection-api-performance which states that so long as I'm careful and only have it in request/dispatch I should be ok since the __call is a dispatcher I shouldn't really feel the strain only thing is it will dispatch every time I create a new form element. I'm gonna get a benchmark running and see what happens.
Sammaye
@Sammaye chances are, your __call invocations without the Reflection code are not exactly fast either. Magic methods come with slowdown too. The big question is will it matter?
Gordon
If I'm already using a _call no...so Long as I never need to make a truely huge form...but then again PHP can handle a lot on the right server so it might be pefectly fine I might just be paraniod over nothing.
Sammaye
Decided to go with this one it was about 1ms quicker than call_user_func_array hopefully it wont cause too much of a strain since I only use this for form element making and nothing else and only once each element then :). thanks for the info :)
Sammaye