2009-06-11 19 views
6

Mam bardzo wyjątkowy przypadek, w którym muszę wywołać metodę chronioną spoza klasy. Jestem bardzo świadomy tego, co robię programując, ale nie byłbym całkowicie przeciwny takiemu w tym jednym szczególnym przypadku, jaki mam. We wszystkich innych przypadkach muszę nadal uniemożliwiać dostęp do metody wewnętrznej, dlatego chciałbym, aby metoda była chroniona.Zadzwoń do metody chronionej spoza klasy w PHP

Jakie są eleganckie sposoby uzyskania dostępu do metody chronionej poza klasą? Do tej pory znalazłem this.

Przypuszczam, możliwe jest tworzenie pewnego rodzaju przykład podwójnego agenta klasy docelowej, które podstępnie zapewniają dostęp do wewnętrznych ...

+0

Najlepszy sposób na zrobienie tego? Zmień funkcję, aby była publiczna. – Powerlord

Odpowiedz

0

Ja tylko rzuca to tam, ponieważ nie mam programowane w PHP za dwa lata. Czy możesz po prostu dodać funkcję do klasy, która nazywa tak zabezpieczoną metodę?

$obj->publicFunc = create_function('$arg', 'return $this->protectedFunc($arg);'); 

Edit: myślę Tom rację patrząc na dokumentacji create_function. Wygląda na to, że zakres $ będzie "zły", gdy spróbujesz wywołać go za pomocą tego przykładu.


Wygląda tradycyjnych funkcji anonimowych są wspierane od PHP 5.3.0, jak również (i moje pierwsze rozwiązanie prawdopodobnie nie będzie działać), więc pewnie bym napisać to tak zamiast:

$obj->publicFunc = function($arg) { 
    return $this->protectedFunc($arg); 
}; 

Ponieważ wydaje mi się, że wygląda trochę czystszy (a twój wybrany IDE podświetli go oczywiście lepiej).


Fuj, próbowałem za pomocą Reflection wywołać metodę PHP, ale nie będzie można to zrobić albo. Wygląda na to, że będziesz musiał użyć jakiejś klasy dziecięcej, tak jak sugerowały inne plakaty. Jeśli znajdziesz metodę, która działa, programiści będą prawdopodobnie klasyfikować ją jako błąd w przyszłości i złamać kod po aktualizacji do następnej wersji.

Polecam rozszerzenie klasy.

+0

Nono, to dobry strzał. Prawdopodobnie spróbuję. Jeśli to zadziała, dam ci znać. –

+0

Myślę, że po prostu utworzymy ciąg $ obj-> publicFunc, który jest nazwą nowej funkcji. Przy próbie wywołania zasięg jest taki sam, jak w normalnej funkcji. –

+1

Nie działa to poprawnie: http://chadjohnson.ath.cx:8080/static/anonymous_function.phps. Otrzymuję błąd "Wezwanie do niezdefiniowanej metody Czad :: publicFunction()." Co mogę robić źle? –

1

To trochę kluda, ale może być opcja.

Dodaj klasę dziecka ze względu na swoją funkcję dostępu zabezpieczonego

public class Child extends Parent { 
    public function protectedFunc() { 
     return parent::protectedFunc(); 
    } 
} 

Następnie wystąpienia wystąpienie Child zamiast Parent gdzie trzeba wywołać tę funkcję.

+0

Hmm, tak, to wygląda jak moja jedyna opcja w tym momencie. Może powinienem nazwać tego Szpiega klasy o_O. –

3

Myślę, że w tym przypadku refaktoryzacja, więc nie wymaga się tego typu rzeczy, jest prawdopodobnie najbardziej elegancką drogą. Mówiąc, że jedną z opcji jest użycie __call i wewnątrz tego parsowania debug_backtrace, aby zobaczyć, która klasa nazwie metodę. Następnie sprawdź znajomych, którzy mają jeden numer:

class ProtectedClass { 

    // Friend list 
    private $friends = array('secret' => array('FriendClass')); 

    protected function secret($arg1, $arg2) { 
     // ... 
    } 

    public function __call($method, $args) { 

     $trace = debug_backtrace(); 
     $class = $trace[1]['class']; 
     if(in_array($class, $this->friends[$method])) 
      return $this->$method($args[0], $args[1]); 

     throw new Exception(); 
    } 
} 

Myślę, że potrzebuję prysznica.

+0

Dlaczego po prostu nie używać odbić? – Smar

0

Zastanowiłabym się, co się dzieje z projektem programu, jeśli muszę zadzwonić do prywatnej funkcji?

Kiedyś to przypadek, gdy

  • klasa jest odpowiedzialna za kilka rzeczy (to naprawdę dwa lub thre calsses zawinięte razem) lub
  • zasady enkapsulacji są łamane (funkcje użytkowe, dla przykładem)

Znajdując dowolny sposób chodzić wokół tego pytania, będziesz nigdzie bliżej do prawdziwego rozwiązania.

+1

Ogólnie jest to dobra rada. Ale czasami istnieją dobre powody, aby wywoływać metody wykraczające poza ich zdefiniowany zakres. Na przykład, jeśli nie chcesz, aby metoda była częścią interfejsu API, ale chcesz wywołać ją w swoich testach. Lub w widokach CodeIgniter, możesz chcieć, aby funkcja hashowania hasła nie była możliwa do wywołania z internetu, ale chcesz wywołać je w swoich testach. W przeciwieństwie do C++, PHP nie ma klas "przyjaciel", które mają uprzywilejowany dostęp do klas wewnętrznych. – qris

+1

Również jeśli używasz API innej firmy, który nie eksponuje metody, ale zdecydowanie potrzebujesz dostępu do tej metody. Zdecydowanie ważny punkt stworzony przez Csaba, ale w bardzo rzadkich przypadkach może być konieczne złamanie zasad. –

-3

Załóżmy, że deklaracja metoda idzie tak:

protected function getTheFoo() { 
    ... 
} 

protected function setTheFoo($val) { 
    ... 
} 

Zastosowanie:

$obj->__get('the_foo'); 
$obj->__set('the_foo', 'myBar'); 

ten omija chronionych metod i idzie bezpośrednio prosto do zmiennych instancji.

+0

Nie otrzymuję tego. – Mateng

4

W PHP można to zrobić za pomocą Reflections. Aby wywołać metody chronione lub prywatne, należy użyć metody setAccessible() http://php.net/reflectionmethod.setaccessible (wystarczy ustawić wartość PRAWDA)

+0

Powinieneś powiedzieć, jak to zrobić, jako odpowiedź, a nie połączyć inną odpowiedź (w tym przypadku dokumentacja). Zachęcamy jednak do linkowania do źródła i innych ważnych fragmentów dokumentacji. – Smar

Powiązane problemy