2010-06-03 18 views
4

Existe-t-il un moyen en PHP5 de n'autoriser qu'une certaine classe ou un ensemble de classes à appeler une fonction particulière? Par exemple, disons que j'ai trois classes ("Foo", "Bar" et "Baz"), toutes avec des méthodes nommées de la même manière, et je veux que Bar puisse appeler Foo::foo() mais refuser à Baz la possibilité de faire cet appel :PHP5: restreindre l'accès à la fonction à certaines classes

class Foo { 
    static function foo() { print "foo"; } 
} 

class Bar { 
    static function bar() { Foo::foo(); print "bar"; } // Should work 
} 

class Baz { 
    static function baz() { Foo::foo; print "baz"; } // Should fail 
} 

Foo::foo(); // Should also fail

Il n'y a pas nécessairement l'héritage entre les Foo, Bar et Baz, donc l'utilisation de protected ou modificateurs similaires ne seront pas aider; cependant, les méthodes ne sont pas forcément statiques (je les ai donc faites ici pour la simplicité de l'exemple).

Répondre

7

Aucune fonctionnalité de langue ne peut vous donner ce comportement, vous semblez vouloir émuler quelque chose comme des classes d'amis C++? Cependant, à l'intérieur de la méthode foo(), vous pouvez utiliser debug_backtrace pour savoir qui était votre appelant et lancer une exception si ce n'est pas ce que vous voulez!

+0

Ce n'est pas un développeur C++, mais après avoir lu (brièvement) à propos des classes d'amis, cela ressemble exactement au comportement que je recherche. Dépression qu'il n'y a pas d'équivalent PHP. – Tim

3

J'ai créé une fonction pour ce faire qui pourrait être utile.

class HelperClass 
{ 

    static function callOnlyByClass($class_name, $function_name = NULL) 
    { 
     $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); 
     $caller_class = $backtrace[2]["class"]; 
     if($caller_class !== $class_name) { 
      throw new Exception("Only $class_name is allowed to call this function. Was called by $caller_class."); 
     } 
     if(! is_null($function_name)) { 
      $caller_function = $backtrace[2]["function"]; 
      if($caller_function !== $function_name) { 
       throw new Exception("Only $class_name::$function_name is allowed to call this function. Was called by $caller_class::$caller_function."); 
      } 
     } 
    } 

} 
1

Un peu fudge, mais si vous vouliez une alternative plus simple moins intensive de la mémoire à l'aide debug_backtrace() vous pourriez avoir besoin d'un argument supplémentaire à la méthode qui devrait être de quelque secret propre valeur. Ainsi, par exemple: -

class Foo { 
    static function foo($arg='') { 
     if ($arg != 'act6hd56') { 
      throw new Exception('Cannot call this method from any class except Bar'); 
     } 
     print "foo"; 
    } 
} 

class Bar { 
    static function bar() { Foo::foo('act6hd56'); print "bar"; } // Works 
} 

Foo::foo(); // Throws exception 

Cela ne l'empêche pas quelqu'un en regardant à travers le code et le travail autour d'elle, mais avec un message sensible dans l'exception, vous devriez être en mesure de transmettre la façon dont vous l'intention des classes à utiliser.

Vous pouvez même aller plus loin et mettre en œuvre quelque chose de très similaire à friend classes en utilisant la magie __call() et __callStatic() méthodes de php de C++, cela signifie que vous pourriez faire la vérification secrète sans polluer les méthodes actuelles. Le désavantage de ceci serait que vous n'obtiendriez pas l'IDE faisant allusion à ces méthodes parce que vous auriez besoin de les préfixer ou de quelque chose, sinon les méthodes magiques sont ignorées.