2011-07-13 12 views
10

Mam interfejs API do interakcji z moją aplikacją internetową, zdefiniowaną przez klasę. Każda publicznie dostępna metoda wymaga uwierzytelnienia przed uruchomieniem. Zamiast umieszczać tę samą linię w kółko w każdej metodzie, chciałbym użyć magicznej funkcji __call. Będzie jednak działać tylko na prywatnych lub chronionych metodach, a moje muszą być publiczne, aby pracować z Zend_Json_Server.__wspólnotowy odpowiednik dla metod publicznych

class MY_Api 
{ 
    public function __call($name, $arguments) 
    { 
    //code here that checks arguments for valid auth token and returns an error if false 
    } 

    public function myFunction($param1, $param2, $param3) 
    { 
    //do stuff when the user calls the myFunction and passes the parameters 
    //this function must remain public so that Zend_Json_Server can parse it 
    //but I want it intercepted by a magic method so that the authentication 
    //can be checked and the system bails before it even gets to this function. 
    } 
} 

Czy można włączyć te publiczne funkcje i ewentualnie anulować ich wykonanie przed wywołaniem?

+0

Czy używasz Zend ACL? –

+0

Jeszcze nie. Nie byłem pewien, czy był odpowiedni do zastosowania w tej sekcji aplikacji. Jest to interfejs API odpoczynku, więc nie loguje się i nie konfiguruje sesji, ale przekazuje token. –

+1

Co nazywa się metodą publiczną i czy wywołujący może wywołać metodę uwierzytelniania? – webbiedave

Odpowiedz

7

__call faktycznie działa dla wszystkich metod, w tym publicznych. Jednak powód, dla którego nie zadziała, jeśli metoda publiczna już istnieje, jest taka, że ​​kod spoza twojej klasy może już mieć dostęp do członków publicznych. __call jest wywoływany tylko dla członków, którzy nie mają dostępu do kodu wywołującego.

O ile wiem, są tam naprawdę nie ma możliwości, aby robić to, co szukasz, chyba że za pomocą pewnego rodzaju wzorzec dekorator:

class AuthDecorator { 
    private $object; 

    public function __construct($object) { 
     $this->object = $object; 
    } 

    public function __call($method, $params) { 
     //Put code for access checking here 

     if($accessOk) { 
      return call_user_func_array(array($this->object, $method), $params); 
     } 
    } 
} 

$api = new MY_Api(); 
$decoratedApi = new AuthDecorator($api); 

//any calls to decoratedApi would get an auth check, and if ok, 
//go to the normal api class' function 
+0

Rozwiązaniem jest tutaj klasyczne programowanie zorientowane na aspekt za pomocą proxy i dokładnie to, czego potrzebujesz. Chciałbym wątpić, że ponieważ '__call()' jest wywoływana tylko wtedy, gdy metoda jest niedostępna i że wszystkie publiczne metody są dostępne, '__call()' może być uznane za niedziałające z publicznymi metodami. Podekscytowałeś mnie myśląc, że może być luka, którą przegapiłem, ale niestety tak nie było. :( –

+0

lub zmiana nazwy wszystkich funkcji, aby dodać "_" do nazwy.Można wywołać metodę 'x', która przejdzie przez _ __call', która następnie wywoła publiczną metodę' x_'. Teraz myślę o to, dekorator prawdopodobnie będzie łatwiejszy :) – GolezTrol

+0

@David Harkness Ah, dzięki - Aspekty były dokładnie tym, o czym miałem zamiar wspomnieć, ale mogłem tylko myśleć o cechach :) Ale tak, masz rację co do __call od z tej perspektywy. –

3

Odkąd poszedłem z moim komentarzem jako możliwe rozwiązanie , Sformatowałem ją jako odpowiedź dla potomności:

Jeśli rozwiązania aspektowe lub dekoratorskie nie działają dla ciebie, możesz wypróbować bardziej oparte na strukturze rozwiązanie, umieszczając kod, który sprawdza uwierzytelnianie w dzwoniący z twojej publicznej metody lub nawet wyżej.

+1

Nie użyłem wcześniej 'Zend_Json_Server', ale jego całujący kuzyn' Zend_Controller_Action' definiuje 'preDispatch()', który jest wywoływany przed rzeczywistą metodą akcji. Być może komponent JSON dostarcza taką funkcję. –

+0

fajny pomysł, @David, ale Zend_Json_Server nie ma i rozszerza Zend_Server_Abstract, który też nie. –

+0

Dzięki za uczynienie z odpowiedzi @webbiedave. To faktycznie zakończyło się rozwiązaniem problemu w tym konkretnym przypadku. –