2008-11-25 10 views
28

Czy istnieje jakiś odpowiednik "znajomego" lub "wewnętrznego" w php? Jeśli nie, czy istnieje jakiś wzór do naśladowania, aby osiągnąć to zachowanie?Odpowiednik PHP znajomego lub wewnętrznego

Edytuj: Niestety, ale standardowe Php nie jest tym, czego szukam. Szukam czegoś podobnego do tego, co zrobił ringmaster.

Mam klasy, które wykonują wywołania systemowe w stylu C na zapleczu, a żonglerka stała się uciążliwa. Mam funkcje w obiekcie A, które przyjmują obiekt B jako parametr i muszą wywoływać metodę w obiekcie B przekazując samą siebie jako argument. Użytkownik końcowy może wywołać metodę w B, a system rozpadnie się.

Odpowiedz

40

PHP nie obsługuje żadnych deklaracji przyjaciela-podobne. Można to symulować za pomocą metod PHP5 __get i __set, a także sprawdzanie śladu wstecznego tylko dla dozwolonych klas przyjaciół, chociaż kod do tego typu jest niezręczny.

Jest trochę sample code i dyskusja na ten temat na stronie PHP:

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); 
    } 
} 

(Kodeks świadczy tsteiner na nerdclub Dot Net on bugs.php.net)

+15

To jest cudowny hack! Kocham to i jestem przez niego odpychany. Sprytnie. +1 –

+1

Jaka jest wydajność z tym? Czy jest to zauważalny hit? To jest dokładnie to, czego szukam. – smack0007

+0

Jest to idealne rozwiązanie do enkapsulacji. Teraz mam klasę główną bez getterów, jeden Accesor, który implementuje moduły pobierające i widok, który jest jedynym, który może korzystać z modułów pobierających. +100 jeśli mógłbym –

-13

Jestem pewien, że to, czego szukasz, jest "chronione" lub "prywatne", w zależności od twojego przypadku użycia.

Jeśli definiowania funkcji w klasie, i chcesz tylko ona dostępna do siebie, będzie to określić w ten sposób:

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

Jeśli definiowania funkcji w klasie, która chcesz mieć dostęp do klas, które dziedziczą z tej klasy, ale nie są dostępne publicznie, zdecydowanie to w ten sposób:

protected function foo($arg1, $arg2) 

Jestem pewien, że domyślnie w PHP5, funkcje są jawne, co oznacza, że ​​nie należy użyć następującej składni, ale jest opcjonalna:

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

Musisz jeszcze utworzyć instancję obiektu przed użyciem funkcji publicznej. Więc ja po prostu być dokładna i poinformować, że w celu korzystania z funkcji w klasie bez instancji obiektu, należy użyć następującej składni:

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

który pozwoli Ci korzystać z funkcji przez tylko odwołanie do klasy, w następujący sposób:

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

w przeciwnym razie trzeba wykonać następujące czynności:

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

myślę co OP pytał było jak zaimplementować w PHP coś podobnego do 'friend' słów kluczowych w języku C++, czyli dokonania pewnych prywatne/chronionych danych/metod dostępnych _to niektórych klas, które zrobił nie odziedziczyć po nim_. – Xenon

5

Możliwe jest również podniesienie uprawnień, aka wyciek danych selektywnie , używając uzgadniania i zamykania w php> = 5.3.3.

Zasadniczo interakcja jest następująca: klasa A ma publiczną metodę akceptującą obiekt klasy B i wywołuje B-> grantAccess (lub jakikolwiek definiuje interfejs użytkownika), przekazując mu zamknięcie. Zamknięcie use($that,$anythingelseyouneed) gdzie $ that = $ this, i wszystko, czego potrzebujesz, aby określić, które właściwości mogą być dostępne. Zamknięcie ma jeden argument - właściwość do zwrotu; jeśli jest to właściwość $ i wszystko jest w porządku, zamknięcie zwraca właściwość.W przeciwnym razie zwraca "" lub zgłasza wyjątek, a może wartość domyślną.

Klasa B-> grantAccess akceptuje żądanie wywołania i przechowuje ją, używając jej w innych metodach do wyodrębnienia prywatnych właściwości, których zamknięcie pozwala na wyciek. Ustaw domyślny konstruktor klasy B jako prywatny. Skonstruuj B za pomocą statycznej metody fabularnej, która pobiera argument klasy A, aby zapewnić uścisk dłoni.

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