2013-11-28 8 views
15

W Slim jest możliwe uzyskanie bieżącej trasy w ramach oprogramowania pośredniego?Wąska trasa PHP w oprogramowaniu pośrednim

class Auth extends \Slim\Middleware{ 
    public function call(){ 
    $currentRoute = $this->app->getRoute(); // Something like this? 
    } 
} 

Wiem, że można zadzwonić $app->router()->getCurrentRoute() po hak slim.before.dispatch nazywa, ale podczas rozmowy to z middleware zwraca non-object. Każda pomoc będzie wielce ceniona.

Odpowiedz

19

Tak i nie. Jeśli spojrzysz na kod źródłowy dla Slim, zobaczysz, że zarejestrowane middleware są wywoływane w kolejności LIFO, gdy wywoływana jest metoda Slim::run, a następnie Slim uruchamia własną metodę "call", w której rozpoczyna się przetwarzanie żądania. Właśnie w tej metodzie Slim analizuje i przetwarza trasę. W takim przypadku nie można uzyskać dostępu do metody $app->router()->getCurrentRoute() w metodzie Middleware::call, ponieważ nie zostanie ona jeszcze przeanalizowana i zdefiniowana.

Jedynym sposobem, aby to zrobić, jest zarejestrowanie detektora na slim.before.dispatch w oprogramowaniu pośredniczącym i zaimplementowanie tego, co chcesz zrobić w tej metodzie.

Od nazwy klasy zakładam, że próbujesz utworzyć podstawowy moduł uwierzytelniania? Robiłem coś podobnego do tego wcześniej, i poszedł coś takiego:

class AuthMiddleware extends \Slim\Middleware 
{ 
    public function call() 
    { 
     $this->app->hook('slim.before.dispatch', array($this, 'onBeforeDispatch')); 

     $this->next->call(); 
    } 

    public function onBeforeDispatch() 
    { 
     $route = $this->app->router()->getCurrentRoute(); 

     //Here I check if the route is "protected" some how, and if it is, check the 
     //user has permission, if not, throw either 404 or redirect. 

     if (is_route_protected() && !user_has_permission()) 
     { 
      $this->app->redirect('/login?return=' . urlencode(filter_input(INPUT_SERVER, 'REQUEST_URI'))); 
     } 
    } 
} 

W tym przykładzie metoda onBeforeDispatch zostanie uruchomiony przed trasy teleskopowe są wywoływane. Jeśli spojrzysz na kod źródłowy, możesz zobaczyć, że zdarzenia są wywoływane wewnątrz bloku try/catch, który nasłuchuje wyjątków generowanych przez $app->redirect() i $app->pass() itd. Oznacza to, że możemy zaimplementować tutaj naszą logikę wyboru/przekierowania, tak jakby to była funkcja obsługi trasy.

Powyżej is_route_protected i user_has_permission są po prostu pseudokodem ilustrującym działanie mojego oprogramowania pośredniego Auth. Skonstruowałem klasę tak, aby można było określić listę tras lub wyrażenie regularne dla tras w konstruktorze oprogramowania pośredniego, które były chronione, a także przekazywać obiekt usługi, który zaimplementował sprawdzanie uprawnień użytkownika itp. Mam nadzieję, że to pomoże.

+0

Niezły. Dzięki za schludne rozwiązanie i szczegółowe wyjaśnienie. Czy zarejestrowanie haka w funkcji wywołania oprogramowania pośredniego() jest dla niego dobrym rozwiązaniem? Wydaje się, że to dlatego, że utrzymuje porządek, zastanawiając się tylko, czy to może spowodować, że haczyk zostanie zarejestrowany/wywołany więcej niż raz? – plong0

+3

Myślę, że można bezpiecznie założyć, że metoda połączenia zostanie wywołana tylko raz na żądanie. W rzeczywistości zależy to od implementacji poprzedniego oprogramowania warstwy pośredniej w łańcuchu, ponieważ projekt korzysta z pojedynczo połączonej listy, z której każde oprogramowanie pośrednie wywołuje następną. Jeśli oprogramowanie pośredniczące wywoła dwa następne w metodzie wywoływania łańcuchów dwa razy, sugeruję jego wykonanie Doing It Wrong ™ i prawdopodobnie powinieneś przestać go używać :). –

+0

dziękuję, to działa – mapodev

2

Powinieneś użyć app-> request() -> getPathInfo() zamiast app-> getRoute().

class Auth extends \Slim\Middleware{ 
    public function call(){ 
     $currentRoute = $this->app->request()->getPathInfo(); 
    } 
} 
3

Istnieje alternatywna metoda robienia tego, ponieważ znajduję się w tej samej sytuacji. Co chciałem uniknąć zostało dopasowane niczego trasie i chciał zamiast używać nazw tras, więc można spróbować wykonać następujące czynności:

public function call() { 

    $routeIWantToCheckAgainst = $this->slimApp->router()->urlFor('my.route.name'); 
    $requestRoute = $this->slimApp->request()->getPathInfo(); 
    if ($routeIWantToCheckAgainst !== $requestRoute) { 
     // Do stuff you need to in here 
    } 

    $this->next->call(); 
} 

Można nawet mieć tablicę tras nie chcesz middleware do uruchomienia na a następnie po prostu sprawdź czy jest to in_array() itd. a jeśli nie, rób to, co potrzebujesz.

Powiązane problemy