2013-11-28 21 views
15

Slim'de mevcut rotayı middleware içinde almak mümkün mü?Slim PHP Route in Middleware

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

Ben slim.before.dispatch kanca denir sonra $app->router()->getCurrentRoute() çağırabilir biliyorum ama katman bu çağırdığınızda olmayan bir nesne döndürür. Herhangi bir yardım büyük takdir edilecektir.

cevap

19

Evet ve hayır. Slim için kaynak koduna bakarsanız, o kayıtlı Middlewares'in, Slim::run yöntemi çağrıldığında LIFO düzeninde çağrıldığını göreceksiniz ve sonra Slim, isteğin işlenmesinin başladığı kendi "çağırma" yöntemini çalıştırır. Bu yöntemde İnce, rotayı ayrıştırır ve işler. Bu durumda, Middleware::call yönteminde $app->router()->getCurrentRoute()'a erişemezsiniz çünkü henüz ayrıştırılmamış ve tanımlanmamıştır.

Bunu yapmanın tek yolu, Middleware'inizde bir dinleyiciyi slim.before.dispatch'a kaydetmek ve bu yöntemde yapmak istediğiniz şeyi uygulamaktır.

Sınıfınızın adından, temel bir kimlik doğrulama modülü oluşturmaya çalıştığınızı mu sanıyoruz? Daha önce buna benzer bir şey yaptık ve böyle bir şey çıktı: onBeforeDispatch yöntem işleyicileri çağrılır güzergahın önce idare edilecek, bu örnekte

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

. Kaynak koduna bakarsanız, olayların $app->redirect() ve $app->pass() vb. Tarafından atılan istisnaları dinleyen try/catch bloğu içinde tetiklendiğini görebilirsiniz. Bu, çek/yönlendirme mantığımızı burada olduğu gibi uygulayabileceğimiz anlamına gelir. rota işleyici işlevi.

is_route_protected ve user_has_permission'un üstünde, auth ara yazılımımın nasıl çalıştığını göstermek için yalnızca bir sözdizimi kodudur. Sınıfı yapılandırarak, korunan Middleware kurucusunun yolları için bir rota veya regex listesi ve kullanıcı izni kontrolünü uygulayan bir servis nesnesinin geçmesini sağlayabilirsiniz. Umarım bu yardımcı olur.

+0

Güzel olan. Düzenli çözüm ve ayrıntılı açıklama için teşekkürler. Kancanın orta yazılımın çağrısı() içinde kaydedilmesi, bunun için iyi bir nokta işlevi görüyor mu? Bunun gibi görünüyor, çünkü sadece bir kez daha kaydedilmiş/kanca çağrılan neden olabilir merak mı, düzenli tutar? – plong0

+3

Arama yönteminin yalnızca istek başına bir kez çalıştırılacağını varsaymak güvenli. Gerçekte, tasarım, her bir ara yazılımın bir sonraki çağrıyı yaptığı tek bağlantılı bir liste kullandığı için, zincirdeki önceki ara katman yazılımının uygulanmasıyla ilgilidir. Eğer bir ara yazılım zincir arama yöntemini bir daha çağırırsa, Doing It Wrong ™ 'ı öneririm ve muhtemelen kullanmayı kesmelisiniz :). –

+0

teşekkürler, bu işe yarıyor – mapodev

2

Uygulama -> getRoute() yerine app-> request() -> getPathInfo() öğesini kullanmalısınız. Ben aynı durumda been olarak

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

, bunu yapmanın alternatif bir yöntem yoktur. Ne yolla şey eşleşen edildi kaçınmak istedi ve denemek böylece aşağıdaki yerine rota isimleri kullanmak istedi: Hatta yollarının bir dizi olabilir

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

Eğer katman üzerinde çalıştırmak istediğiniz YAPMAYIN ve sonra sadece in_array() vb. olup olmadığını kontrol edin ve eğer gerekmiyorsa, ihtiyacınız olanı yapın.