Вызов статического метода класса по имени

Это несколько вторая часть этого вопроса.

В моем проекте у меня есть следующий интерфейс:

interface ISoapInterface {
  public static function registerSoapTypes( wsdl &$wsdl );
  public static function registerSoapOperations( NuSoapServer &$server );
  public static function registerFaultHandler( $callback );
  public static function handleFault( $faultcode, $faultstring, $faultdetail );
  public static function userInfo( User $user );
}

Теперь у меня есть несколько классов, которые реализуют этот интерфейс, и я хочу вызвать несколько из этих методов для каждого из этих классов.

Таким образом, есть два способа, которыми я могу вызвать эти методы. Версия до 5.3:

call_user_func_array( array( $provider, "registerSoapTypes" ), array( $server->wsdl ) );

И версия после 5.3:

$provider::registerSoapTypes( $server->wsdl );

Теперь моя проблема в том, что версия до 5.3 не работает вообще в 5.3.3.
Parameter 1 to Foo::registerSoapTypes() expected to be a reference, value given
Несмотря на то, что я уверен, что с 5.3.0 он работал нормально. В документации также говорится:

Ссылочные переменные в param_arr передаются в функцию по ссылке, независимо от того, ожидает ли функция передачи соответствующего параметра по ссылке. Эта форма передачи времени вызова по ссылке не выдает уведомления об устаревании, но, тем не менее, не рекомендуется и, скорее всего, будет удалена в следующей версии PHP.

Так что я подумал, что я очень умный, готовя это:

$soapProvider = array( "Foo", "Bar", "Foo2", "Bar2" );
foreach( $soapProvider as $provider ) {

  if( !defined( "PHP_VERSION_ID" ) ) {
    $version = explode( ".", PHP_VERSION );
    define( "PHP_VERSION_ID", ( $version[ 0 ] * 10000 + $version[ 1 ] * 100 + $version[ 2 ] ) );
  }

  if( PHP_VERSION_ID > 50300 ) {
    // Use simple calling method on systems running PHP 5.3.0 or higher
    $provider::registerSoapTypes( $server->wsdl );
    $provider::registerSoapOperations( $server );
    $provider::registerFaultHandler( "faultHandler" );
    $provider::userInfo( $user );

  } else {
    call_user_func_array( array( $provider, "registerSoapTypes" ), array( $server->wsdl ) );
    call_user_func_array( array( $provider, "registerSoapOperations" ), array( $server ) );
    call_user_func_array( array( $provider, "registerFaultHandler" ), array( "faulthandler" ) );
    call_user_func_array( array( $provider, "userInfo" ), array( $user ) );
  }
}

Оказывается, это было совсем не умно, так как $provider::something() генерирует ошибку парсера (Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM).

Итак, как вызвать те статические методы в этих классах (когда имя класса является провайдером в виде строки), который работает на PHP 5.2.6 (Debian 5) - 5.3.3 (Debian 6).

2 ответа

Решение

Как писал Знаркус, вы не передаете ссылку на Foo::registerSoapTypes,

так что просто добавьте & к тем параметрам, которые должны быть переданы как ссылки, во второй параметр вашего call_user_func_array

call_user_func_array( array( $provider, "registerSoapTypes" ), array( &$server->wsdl ) );

Но если не все ваши методы ожидают, что параметры будут ссылочными, вы можете столкнуться с некоторыми проблемами, поэтому, возможно, безопаснее построить $args для call_user_func_array используя некоторое отражение.

Смотрите: http://www.php.net/manual/en/book.reflection.php

и особенно: http://www.php.net/manual/en/reflectionparameter.ispassedbyreference.php

Параметр от 1 до Foo::registerSoapTypes() должен быть ссылкой, данное значение

С помощью call_user_func вместо call_user_func_array должен это исправить.

Другие вопросы по тегам