3

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.

Oliver Salzburg
  • 21,652
  • 20
  • 93
  • 138

2 Answers2

6

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);
}
user229044
  • 232,980
  • 40
  • 330
  • 338
  • 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. – Oliver Salzburg Oct 19 '10 at 16:18
  • @gencha I missed the `static`; will update my answer accordingly. – user229044 Oct 19 '10 at 16:25
3

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
  • 163,128
  • 34
  • 264
  • 314
  • This actually works perfectly, I'm just still wondering if I'm missing something about meagar's solutions. Thanks – Oliver Salzburg Oct 19 '10 at 16:27
  • 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 Oct 19 '10 at 16:31