2008-11-25 11 views
28

Gibt es in php ein Äquivalent von "Freund" oder "intern"? Wenn nicht, gibt es ein Muster, um dieses Verhalten zu erreichen?PHP-Äquivalent von Freund oder intern

Edit: Sorry, aber Standard Php ist nicht das, was ich suche. Ich bin auf der Suche nach etwas, was der Zirkusdirektor getan hat.

Ich habe Klassen, die C-style Systemaufrufe auf dem Back-End tun und das Jonglieren hat begonnen, umständlich zu werden. Ich habe Funktionen im Objekt A, die das Objekt B als Parameter aufnehmen und eine Methode im Objekt B aufrufen müssen, die sich selbst als Argument übergeben wird. Der Endbenutzer könnte die Methode in B aufrufen und das System würde auseinanderfallen.

Antwort

40

PHP unterstützt keine keine Freund-ähnliche Erklärungen. Es ist möglich, dies mit den Methoden PHP5 __get und __set zu simulieren und ein Backtrace nur für die erlaubten Freundesklassen zu untersuchen, obwohl der Code dafür etwas unhandlich ist.

Es gibt einige sample code und Diskussion über das Thema auf der PHP-Website:

class HasFriends 
{ 
    private $__friends = array('MyFriend', 'OtherFriend'); 

    public function __get($key) 
    { 
     $trace = debug_backtrace(); 
     if(isset($trace[1]['class']) && in_array($trace[1]['class'], $this->__friends)) { 
      return $this->$key; 
     } 

     // normal __get() code here 

     trigger_error('Cannot access private property ' . __CLASS__ . '::$' . $key, E_USER_ERROR); 
    } 

    public function __set($key, $value) 
    { 
     $trace = debug_backtrace(); 
     if(isset($trace[1]['class']) && in_array($trace[1]['class'], $this->__friends)) { 
      return $this->$key = $value; 
     } 

     // normal __set() code here 

     trigger_error('Cannot access private property ' . __CLASS__ . '::$' . $key, E_USER_ERROR); 
    } 
} 

(-Code von tsteiner bei nerdclub bewiesen dot net on bugs.php.net)

+15

Das ist ein schöner Hack! Ich liebe es und bin davon abgestoßen. Clever aber. +1 –

+1

Wie ist die Leistung dabei? Ist es ein spürbarer Erfolg? Das wäre genau das, wonach ich suche. – smack0007

+0

Dies ist perfekt für die Verkapselung. Jetzt habe ich eine Main-Klasse ohne Getters, einen Accesor, der die Getter implementiert und einen View, der der einzige ist, der die Getter verwenden kann. +100 wenn ich könnte –

-13

Ich bin mir ziemlich sicher, was Sie suchen, ist "geschützt" oder "privat", abhängig von Ihrem Anwendungsfall.

Wenn Sie eine Funktion in einer Klasse sind definiert, und Sie wollen es nur auf sich selbst zur Verfügung, werden Sie es auf diese Weise definieren:

private function foo($arg1, $arg2) { /*function stuff goes here */ } 

Wenn Sie eine Funktion in einer Klasse sind definiert, die Sie wollen Klassen zur Verfügung stehen, die von dieser Klasse erben, aber nicht öffentlich verfügbar, bestimmt es so:

protected function foo($arg1, $arg2) 

ich bin ziemlich sicher, dass in PHP5 standardmäßig Funktionen öffentlich sind, was bedeutet, Sie dies nicht tun muss die folgende Syntax verwenden, aber es ist optional:

public function foo($arg1, $arg2) { /*function stuff goes here */ } 

Sie müssen das Objekt noch instanziieren, bevor Sie eine öffentliche Funktion verwenden. So komme ich nur gründlich und lassen Sie wissen, dass, um eine Funktion in einer Klasse zu verwenden, ohne ein Objekt zu erhalten, müssen Sie die folgende Syntax verwenden:

static function foo($arg1, $arg2) { /*function stuff goes here */ } 

Das ermöglicht es Ihnen, die Funktion zu nutzen, indem nur Verweis auf die Klasse, wie folgt:

MyClass::foo($a1, $a2); 

Andernfalls müssen Sie folgendes tun:

$myObject = new MyClass(); 
$myObject->foo($a1, $a2); 
+2

Ich denke, was die OP war, zu fragen, wie in PHP etwas ähnlich das 'friend' Schlüsselwort in C++, dh mit dem bestimmten privaten/geschützten Daten/Methoden zur Verfügung _to bestimmten Klassen zu implementieren, die taten nicht erben von it_. – Xenon

5

Es ist auch möglich, Berechtigungen zu erhöhen, auch bekannt als Daten undichte selektiv , mit einem Handschlag und Schließungen in php> = 5.3.3.

Im Grunde geht die Interaktion: Klasse A hat eine öffentliche Methode, die ein Objekt der Klasse B akzeptiert und B-> grantAccess (oder was auch immer Ihre Schnittstelle definiert) aufruft. Die Schließung use($that,$anythingelseyouneed), wobei $ that = $ this, und alles, was Sie sonst noch benötigen, um zu bestimmen, auf welche Eigenschaften zugegriffen werden darf. Die Schließung hat ein Argument - die Eigenschaft zurückzukehren; Wenn es eine Eigenschaft auf $ ist und alles cool ist, gibt die Schließung die Eigenschaft zurück.Andernfalls wird '' zurückgegeben oder eine Ausnahme oder ein Standardwert ausgelöst.

Klasse B-> grantAccess akzeptiert eine aufrufbar und speichert sie, indem sie es in anderen Methoden nutzt, um private Eigenschaften herauszupicken, die der Verschluss durchlecken kann. Machen Sie den Standardkonstruktor der Klasse B privat. Konstruieren Sie ein B mithilfe einer statischen Factory-Methode, die ein Argument der Klasse A verwendet, um sicherzustellen, dass der Handshake stattfindet.

Gist hier: https://gist.github.com/mcamiano/00592fb400e5043d8acd