2010-10-19 6 views
3

Étant donné l'interface suivante:PHP Pass-by-référence incontournable?

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

Et le code suivant:

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

FilePool et UserList à la fois mettre en œuvre ISoapInterface.

PHP se plaindra les deux appels à l'intérieur du foreach indiquant:

Call-temps passe par référence a été désapprouvée

Je regardé ce message, et the documentation semble tout à fait clair sur la façon de résoudre ce problème. Suppression de l'esperluette de l'appel réel.
Alors j'ai changé mon code pour ressembler à ceci:

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

Maintenant, PHP se plaint

Paramètre 1 à Filepool :: registerSoapTypes devraient être référence, la valeur donnée
Paramètre 1 à Filepool :: registerSoapOperations devrait être référence, valeur donnée

En plus de cela, la fonctionnalité est maintenant cassée. Donc, cela ne peut évidemment pas être la solution.

Répondre

6

De l'call_user_func:

Notez que les paramètres de call_user_func() ne sont pas passés par référence.

Pour appeler des méthodes statiques vous pouvez utiliser la syntaxe Class::method(), fournissant une variable pour la Class et/ou method parties:

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

Si j'utilise $ provider-> registerSoapTypes, je reçois Appel à la fonction membre registerSoapTypes sur un non-objet. Les méthodes sont statiques. C'est ce qui m'amène d'abord à call_user_func, si je me souviens bien. –

+0

@gencha J'ai raté le 'static'; mettra à jour ma réponse en conséquence. – meagar

+0

Fonctionne très bien et le code a l'air mieux. Bravo –

3

Alors que call_user_func ne passe pas les paramètres par référence, call_user_func_array peut.

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

La seule différence est qu'il attend un tableau de paramètres au lieu d'une liste de paramètres comme call_user_func (semblable à la différence entre sprintf et vsprintf) ...

+0

Cela fonctionne réellement parfaitement, je me demande toujours si je manque quelque chose sur les solutions de Meagar. Merci –

+0

Eh bien, la solution de @ meagar est très bien. C'est juste appeler la méthode directement plutôt que d'invoquer une fonction pour le faire. C'est comme faire '$ object-> method()', mais pour les méthodes statiques 'class :: method()' ou '$ className :: method()' où '$ className' contient un nom de chaîne de la classe (comme dans votre code original). Les deux solutions fonctionnent [email protected] meagar's est un peu plus rapide et plus efficace, mais le mien est plus flexible (le 'callback' peut être n'importe quoi, et le nombre d'arguments peut être variable). Les deux sont valides ... – ircmaxell