views:

44

answers:

2

Given the following interface:

interface ISoapInterface {
  public static function registerSoapTypes( &$wsdl );
  public static function registerSoapOperations( &$server );
}

And the following code:

$soapProvider = array( "FilePool", "UserList" );
foreach( $soapProvider as $provider ) {
  call_user_func( array( $provider, "registerSoapTypes" ), &$server->wsdl );
  call_user_func( array( $provider, "registerSoapOperations" ), &$server );
}

FilePool and UserList both implement ISoapInterface.

PHP will complain about the two calls inside the foreach stating:

Call-time pass-by-reference has been deprecated

So I looked that message up, and the documentation seems quite clear on how to resolve this. Removing the ampersand from the actual call.
So I changed my code to look like this:

$soapProvider = array( "FilePool", "UserList" );
foreach( $soapProvider as $provider ) {
  call_user_func( array( $provider, "registerSoapTypes" ), $server->wsdl );
  call_user_func( array( $provider, "registerSoapOperations" ), $server );
}

Now PHP complains

Parameter 1 to FilePool::registerSoapTypes expected to be reference, value given
Parameter 1 to FilePool::registerSoapOperations expected to be reference, value given

In addition to that, the functionality is now broken. So this obviously can't be the solution.

+5  A: 

From the call_user_func:

Note that the parameters for call_user_func() are not passed by reference.

To invoke static methods you can use Class::method() syntax, supplying a variable for the Class and/or method parts:

$soapProvider = array( "FilePool", "UserList" );
foreach( $soapProvider as $provider ) {
  $provider::registerSoapTypes($server->wsdl);
  $provider::registerSoapOperations($server);
}
meagar
If I use $provider->registerSoapTypes, I get Call to member function registerSoapTypes on a non-object. The methods are static. That's what initially lead me to call_user_func, if I remember correctly.
gencha
@gencha I missed the `static`; will update my answer accordingly.
meagar
@meagar Works great and the code looks better. Cheers
gencha
+2  A: 

While call_user_func does not pass parameters by reference, call_user_func_array can.

$callback = array($provider, 'blahblahblah');
call_user_func_array($callback, array( &$server ));

The only real difference is that it expects an array of parameters instead of a list of parameters like call_user_func (similar to the difference between sprintf and vsprintf)...

ircmaxell
This actually works perfectly, I'm just still wondering if I'm missing something about meagar's solutions. Thanks
gencha
Well, @meagar's solution is fine. It's just calling the method directly rather than invoking a function to do it. It's like doing `$object->method()`, but for static methods `class::method()` or `$className::method()` where `$className` holds a string name of the class (as in your original code). Both solutions work fine. @meagar's is a little faster and more efficient, but mine is more flexible (the `$callback` can be anything, and the number of arguments can be variable). Both are valid...
ircmaxell