2010-01-21 3 views
51

S'il vous plaît, quelqu'un expérimenté en PHP pourrait aider avec ce qui suit. Quelque part dans mon code, j'ai un appel à une méthode statique publique dans une classe non instancié:Appel de méthode statique dynamique en PHP?

$result = myClassName::myFunctionName(); 

Cependant, je voudrais avoir beaucoup de ces classes et de déterminer le nom de la classe correcte à la volée selon la la langue de l'utilisateur. En d'autres termes, j'ai:

$language = 'EN'; 

... et je dois faire quelque chose comme:

$result = myClassName_EN::myFunctionName(); 

Je sais que je pourrais passer la langue en tant que paramètre à la fonction et faire face à l'intérieur juste une classe commune mais pour diverses raisons, je préférerais une solution différente.

Cela a-t-il un sens, quelqu'un? Merci.

+1

Pour répondre à vos 3 dernières lignes, non, cela n'a pas beaucoup de sens, sauf si vous avez une raison particulière pour laquelle vous ne pouvez pas implémenter le "pass language as parameter" façon –

+3

Oui, j'ai une raison spécifique ... Cela concerne la gestion des traductions d'une manière plus saine pour diverses choses qui se produisent dans ces classes. C'est compliqué :) – Tom

Répondre

96

Utilisez la fonction call_user_func:

http://php.net/manual/en/function.call-user-func.php

Exemple:

call_user_func('myClassName_' . $language . '::myFunctionName'); 
+24

Combiné avec 'is_callable' et' method_exists' ce serait aussi ma recommandation. Pour passer les paramètres regardez 'call_user_func_array' http://php.net/is_callable http://php.net/method_exists http://php.net/call_user_func_array –

+1

+1, je suis d'accord :-) –

+0

Ce genre de travaux et semble être la solution la plus propre. Merci – Tom

3

bien que je pense que la façon dont vous traitez est une très mauvaise idée, je pense que je pourrais avoir une solution

$className = 'myClassName_'.$language; 
$result = $className::myFunctionName(); 

je pense que c'est ce que vous voulez

+0

haha ​​snap! vous me battez par 45s –

+0

S'il vous plaît pourriez-vous me dire pourquoi c'est une si mauvaise idée? – Tom

+0

vous pouvez utiliser la langue comme paramètre, à la place vous choisissez de définir une nouvelle classe pour cela. Dites que vous voulez soutenir 200 langues différentes, allez-vous vous asseoir et écrire 200 classes différentes. Cela rendra votre code extrêmement difficile à lire et à comprendre. – marvin

12

Je pense que vous pourriez faire:

$classname = 'myClassName_' . $language; 
$result = $classname::myFunctionName(); 

Ceci est appelé Variable Functions

+4

C'est dommage que cela ne fonctionne que dans = = 5.3.0 :( –

+0

Pour moi , c'est la meilleure solution et selon mon banc, c'est aussi le plus rapide: 100.000 itérations ont pris 0.28s avec appel direct, 0.32 avec cette solution, et 0.47 avec call_user_func – fred727

1

Pour autant que je pouvais comprendre votre question, vous devez obtenir le nom de la classe qui peut être fait en utilisant get_class fonction . D'un autre côté, le Reflection class peut vous aider ici, ce qui est génial quand il s'agit de méthodes, d'arguments, etc.

13

Je voudrais encapsuler la création de la classe dont vous avez besoin dans une usine. De cette façon, vous aurez un seul point d'entrée lorsque vous devrez changer votre nom de base ou les règles pour mapper la langue à la bonne classe.

class YourClassFactory { 

     private $_language; 
     private $_basename = 'yourclass'; 

     public YourClassFactory($language) { 
      $this->_language = $language; 
     } 

     public function getYourClass() { 
      return $this->_basename . '_' . $this->_language; 
     }  
    } 

puis, quand vous devez l'utiliser:

$yourClass = $yourClassFactoryInstance->getYourClass(); 
$yourClass::myFunctionName(); 
0

Solutions comme:

$yourClass::myFunctionName(); 

ne fonctionnera pas. PHP va produire une erreur d'analyse. Malheureusement, la seule façon est d'utiliser très lentcall_user_func().

+3

Seulement dans <5.3.0 cela n'est pas autorisé. 5.3.0 c'est autorisé –

+0

http://uk3.php.net/manual/fr/language.variables.variable.php et http://uk3.php.net/manual/fr/functions.variable-functions. php :) – tftd

6

Comme dit Temuri, erreur d'analyse est produit, en essayant 'className $ :: functionName':

Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM ...

Dans mon cas (méthode statique avec 2 arguments), les meilleures solutions est d'utiliser call_user_func_array avec 2 tableaux (comme suggéré par nikc.org):

$result = call_user_func_array(array($className, $methodName), array($ard1, $arg2)); 

BR

-1

Je sais qu'il est un vieux fil, mais à partir de PHP 5.3.0, vous devez utiliser forward_static_call

$result = forward_static_call(array('myClassName_EN', 'myFunctionName')); 

Utilisation de votre variable langage $, il pourrait ressembler à:

$result = forward_static_call(array('myClassName_' . $language, 'myFunctionName')); 
+0

Ne fonctionne pas. Appelle une fonction définie par l'utilisateur ou une méthode donnée par le paramètre function, avec les arguments suivants. Cette fonction doit être appelée dans un contexte de méthode, elle ne peut pas être utilisée en dehors d'une classe ... comme mentionné dans http://php.net/manual/fr/function.forward-static-call.php –

1

Vous pouvez facilement faire ensuite:

<?php 

class B { 

    public static $t = 5; 

    public static function t($h) { 
     return "Works!" . $h; 
    } 
} 

$g = 't'; 
$class = 'B'; 

echo $class::$g('yes'); //Works! Yes 

Et il sera fonctionne très bien, testé sur PHP 5.2> =

Questions connexes