Llamar al método estático de la clase por su nombre

Esta es, en cierto modo, la segunda parte de esta pregunta.

En mi proyecto, tengo la siguiente interfaz:

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 );
}

Ahora tengo varias clases que implementan esta interfaz y quiero llamar a varios de estos métodos en cada una de esas clases.

Entonces, hay 2 formas en que puedo invocar esos métodos. La versión anterior a 5.3:

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

Y la versión posterior a 5.3:

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

Ahora, mi problema es que la versión anterior a 5.3 no funciona en absoluto en 5.3.3.
Parameter 1 to Foo::registerSoapTypes() expected to be a reference, value given
Aunque estoy bastante seguro de que funcionó bien con 5.3.0. La documentación también dice:

Las variables referenciadas en param_arr se pasan a la función por referencia, independientemente de si la función espera que el parámetro respectivo se pase por referencia. Esta forma de pase de tiempo de llamada por referencia no emite un aviso de desaprobación, pero es No obstante, en desuso, y lo más probable es que se elimine en la próxima versión de PHP.

Así que pensé que estaba siendo muy inteligente al cocinar esto:

$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 ) );
  }
}

Resulta que no fue nada inteligente, ya que $provider::something() genera un error del analizadorParse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM).

Entonces, ¿cuál es la forma de llamar a esos métodos estáticos en esas clases (cuando el nombre de la clase es proveedor como una cadena) que funciona en PHP 5.2.6 (Debian 5) a 5.3.3 (Debian 6)?

preguntado el 16 de mayo de 11 a las 17:05

2 Respuestas

Como escribió Znarkus, no está pasando una referencia a Foo::registerSoapTypes,

así que solo agrega un & a los parámetros que deben pasarse como referencias, en el segundo parámetro de su call_user_func_array

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

Pero si no todos sus métodos esperan que los parámetros sean una referencia, podría tener algunos problemas, por lo que tal vez sea más seguro construir los $ args para call_user_func_array usando un poco de reflexión.

Ver: http://www.php.net/manual/en/book.reflection.php

y especialmente: http://www.php.net/manual/en/reflectionparameter.ispassedbyreference.php

contestado el 16 de mayo de 11 a las 21:05

De alguna manera pensé que eso tampoco era legal. Dado que la documentación dice: No hay un signo de referencia en una llamada de función, solo en las definiciones de función. Las definiciones de funciones por sí solas son suficientes para pasar correctamente el argumento por referencia. A partir de PHP 5.3.0, recibirá una advertencia que dice que la "transferencia de tiempo de llamada por referencia" está en desuso cuando usa & in foo (& $ a) ;. - Der Hochstapler

Se espera que el parámetro 1 de Foo :: registerSoapTypes () sea una referencia, valor dado

Usar call_user_func en lugar de call_user_func_array debería arreglar eso.

contestado el 16 de mayo de 11 a las 21:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.