2010-06-16 4 views
3

Étant donné que ma classe ressemble à ceci:Est-il possible de restreindre la façon dont une méthode peut être appelée en PHP?

class Methods{ 
    function a(){ 
     return 'a'; 
    } 

    function b(){ 
     $this->a(); 
    } 

    function c(){ 
     $this->a(); 
    } 
} 

Est-il possible d'assurer qu'une fonction peut être appelée ne de la fonction b?

Dans l'exemple ci-dessus, la fonction c doit échouer. Je pourrais l'inclure dans la fonction b, mais à l'avenir je veux laisser a() être appelé par quelques nouvelles fonctions (par exemple d() ou e ())

+2

Non (vilains hacks exclus). Et pourquoi voudriez-vous ça de toute façon? Qu'est-ce que vous essayez d'accomplir? – Artefacto

+1

OK Je vais prendre une autre route, étant donné que le consensus général est que cette idée suce ... – Ash

+2

Si 'c()' ne devrait pas appeler 'a()' ne pas invoquer dans 'c()' – Gordon

Répondre

8

Commencez par l'apprentissage de la différence entre les méthodes public, private and protected ... il est utile de avoir au moins une compréhension des bases de la POO avant de vouloir faire quelque chose d'incroyablement compliqué comme ça. Oui, il est possible d'utiliser debug_backtrace() pour identifier l'origine de l'appel à la méthode; mais c'est un très gros frais généraux ... et je ne vois aucune utilité à établir une telle restriction.

0

Pas vraiment.

  • Vous pouvez vérifier l'appelant en vérifiant le résultat de debug_backtrace()
  • Vous pouvez le rendre privé pour l'éviter d'être appelé à l'extérieur de la classe, puis déplacez c() en dehors de la classe.
2

Vous devriez d'abord regarder les modificateurs de visibilité de classe, comme Mark Baker l'a suggéré. C'est probablement ce que vous cherchez.

Cependant, si ce n'est pas, le code devrait fonctionner pour vous:

class Methods 
{ 
    private function a() 
    { 
     $bt = debug_backtrace(); 
     if(!isset($bt[1]) || $bt[1]['function'] != 'b' || $bt[1]['class'] != get_class($this)) 
     { 
      //Call not allowed 
      return NULL; 
     } 
    } 
    function b() 
    { 
     //allowed 
     $this->a(); 
    } 
    function c() 
    { 
     //not allowed 
     $this->a(); 
    } 
} 
+3

Ce code sent vraiment ... c'est une bonne solution cependant. – Cristian

0

Je ne vois pas à restreindre les méthodes à l'intérieur du même classe pour appeler d'autres méthodes.

Peut-être que votre modèle est faux et que vous devez créer deux classes? Une classe doit être une unité logique (en quelque sorte).

Si vous utilisez des classes séparées, vous pouvez utiliser le private keyword sur la méthode a et il ne peut plus être appelé depuis l'extérieur de la classe.

1

La méthode la plus proche de ce que vous demandez est closure (aka anonymous function)au sein de la méthode que vous souhaitez restreindre. Les fermetures ne sont pas accessibles en dehors de la méthode dans laquelle elles sont définies. Elles sont généralement utilisées pour définir des rappels et transmises à d'autres méthodes, mais vous pouvez les appeler directement.

class Methods{ 
    function b(){ 
    $a = function() { 
     return 'a'; 
    }; // don't forget the trailing ';' 

    $a(); 
    } 

    function c(){ 
    $this->a(); // fails 
    } 
} 

Faire une méthode privée ou protégés va l'empêcher d'être appelé à l'extérieur de la classe, mais ne limiteront pas les méthodes à l'intérieur de la classe ont accès. À un certain niveau, vous devez faire confiance à votre code pour suivre les règles d'utilisation de votre API.

Les classes sont généralement l'encapsulation d'unités pour l'approbation et si vous rendez la méthode privée d'utilisation extérieure, et que vous la documentez, vous devriez être en mesure de croire qu'elle est utilisée correctement à l'intérieur de la classe. Sinon, peut-être que cette classe est devenue trop grande et il est temps de refactoriser.Comme l'indique @Sjoerd, vous pouvez également inspecter la pile des appels, mais être d'accord avec @ Baker pour dire qu'il n'y a pas ou peu de valeur à cela; Cela s'apparente à un abus de langage et fait de votre code un gâchis.

0

Les éléments suivants peuvent s'appliquer à votre question.

class First { 
    public function a() { 
     $second = new Second(); 

     // Works in this context! 
     $second->b($this); 
    } 
} 

class Second { 
    public function b($context) { 
     if (!$context instanceof First) 
      throw new Exception('Can only be called from context of "First".'); 
     echo 'b'; 
    } 
} 

class Third { 
    public function c() { 
     $second = new Second(); 

     // Doesn't work out of context. 
     $second->b($this); 
    } 
} 

Avertissement Cela ne l'empêche pas Third d'invoquer la méthode, car elle pourrait fournir une référence à une instance de Second. Mais cela rend le processus plus strict et votre documentation peut indiquer pourquoi cela fonctionne de cette manière.

Peut-être que ce sera utile, il semblait s'appliquer à un problème similaire que j'avais assez bien.

Questions connexes