2010-11-04 29 views
1

Voici la prémisse:arguments de la fonction dynamique et en utilisant __call

J'ai beaucoup de classes où je dois effectuer une action AVANT toute méthode de l'une des classes est appelé, était ma solution pour avoir toutes les classes s'étendre un classe parente qui définirait une fonction call() qui ressemblerait à ceci:

public function call($method){ 
    //do the something I need to do before method calls 
    $params = func_get_args(); 
    //remove the $method param from the $params array 
    unset($params[0]); 
    return $this->__call($method,$params); 
} 

et puis appelez simplement la méthode d'appel et préciser la méthode réelle que je voulais appeler, de cette façon la méthode obtiendrait appelé, mais à l'intérieur méthode d'appel (dont la classe hérite de ma classe parente) Je pourrais effectuer l'action dont j'avais besoin avant d'obtenir la méthode spécifiée appelé. Cela doit pouvoir prendre en charge les arguments qui peuvent être des tableaux ou des chaînes, donc tout ce qui implique l'implosion d'un tableau d'arguments ne fonctionnera pas (puisque cela supposerait que tous les arguments sont des chaînes). Je ne suis pas sûr si ce que j'ai ci-dessus est logique, et je voulais vérifier et voir si je vais à ce sujet dans le mauvais sens ou non.

Toutes les idées/pensées seraient grandement appréciées.

Merci! PS: Je dois noter que ma description de la situation ci-dessus donne l'impression que la raison pour laquelle les classes enfants étendent le parent est simplement à cette fin, en réalité il y a plus de raisons (ma classe parente étend Zend_Db_Table_Abstract et mes modèles de base de données étendre le parent).

Répondre

2

__call est appelée automatiquement, si elle est définie, chaque fois que vous essayez d'appeler une fonction qui n'existe pas. C'est pourquoi c'est une méthode "magique". Il me semble étrange de l'utiliser directement, plutôt que dans le contexte pour lequel il est destiné. Ici, vous pourriez aussi bien l'avoir nommé. Vous pouvez utiliser ici la puissance de __call. Essayez de nommer toutes les fonctions membres avec un trait de soulignement avant eux. Donc, si vous aviez auparavant $this->print() vous auriez maintenant $this->_print(). Ensuite, dans votre fonction __call, ajoutez le trait de soulignement et appelez la fonction en utilisant call_user_func_array(array($this,"_$name"), $params). Maintenant, vous pouvez appeler vos fonctions normalement (bien, sans le trait de soulignement).

Cependant, je ne suggérerais pas d'utiliser __call sauf pour des raisons pratiques. À long terme, il est préférable d'appeler n'importe quel code que vous voulez exécuter directement.

+0

Ouais, j'ai réalisé après une falsification __call, ce n'est pas conçu pour être utilisé de la manière que je tente de l'utiliser. Je suppose que mon problème actuel est de pouvoir passer un tableau de valeurs mixtes (certains tableaux, certaines chaînes etc ...) en tant qu'arguments séparés de la méthode appelée. – machinemessiah

+0

Qu'est-ce qui vous empêcherait de transmettre un tableau de valeurs mixtes en tant qu'arguments? N'est-ce pas ce que 'call_user_func' est pour? – theazureshadow

+0

Pas call_user_func, mais call_user_func_array, le premier passe simplement votre tableau d'arguments en un seul argument (un tableau), ce dernier a résolu mon problème, merci pour votre poussée dans la bonne direction! – machinemessiah

1

Une alternative meilleure/plus propre pourrait être de configurer un système d'événement et d'écoute, comme le Doctrine Events System. (Ce code provient en fait de la bibliothèque commune, pas de la partie ORM.) Mais vous aurez besoin de toutes vos méthodes pour distribuer les événements. J'essaie d'éviter d'utiliser __call autant que possible car cela rend votre code plus difficile à comprendre et à maintenir, même si je pense que c'est bien d'utiliser dans les systèmes Plugin.

1

Merci pour les suggestions, je suis une sorte d'aboyer le mauvais arbre, mais voici la solution que je suis venu avec:

public function call($method){ 
    //do the something I need to do before method calls 
    $params = func_get_args(); 
    //remove the $method param from the $params array 
    unset($params[0]); 
    return call_user_func_array(array($this,$method),$params); 
} 

Merci encore les gars!

0

vous pouvez obtenir les paramètres de la méthode directement à partir des paramètres de __call:

function __call($method, $args) { 
    return call_user_func_array(array($this,$method),$args); 
}