Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to forward an HTTP request with Slim Framework

Is it possible to forward a request in Slim? The meaning of "forward", like in JavaEE, is to internally redirect to another route without return the response to the client and maintaining the model.

For example:

$app->get('/logout',function () use ($app) {
   //logout code
   $app->view->set("logout",true);
   $app->forward('login'); //no redirect to client please
})->name("logout");

$app->get('/login',function () use ($app) {
   $app->render('login.html');
})->name("login");
like image 397
Tobia Avatar asked Jan 15 '15 10:01

Tobia


2 Answers

In my opinion, the best way to do this would be by using Slim's internal router (Slim\Router) capabilities and dispatching (Slim\Route::dispatch()) the matched route (meaning: executing the callable from a matched route without any redirect). There are a couple of options that come to mind (depending on your setup):

1. calling a named route + callable doesn't take any arguments (your example)

$app->get('/logout',function () use ($app) {
   $app->view->set("logout",true);

   // here comes the magic:
   // getting the named route
   $route = $app->router()->getNamedRoute('login');

   // dispatching the matched route
   $route->dispatch(); 

})->name("logout");

This should definitely do the trick for you, but I still want to show the other scenarios ...


2. calling a named route + callable with arguments

The above example will fail ... because now we need to pass arguments to the callable

   // getting the named route
   $route = $app->router()->getNamedRoute('another_route');

   // calling the function with an argument or array of arguments
   call_user_func($route->getCallable(), 'argument');

Dispatching the route (with $route->dispatch()) will invoke all middleware, but here we are just calling the the callable directly ... so to get the full package we should consider the next option ...


3. calling any route

Without named routes we can get a route by finding the one matching the a http method and pattern. For this we use Router::getMatchedRoutes($httpMethod, $pattern, $reload) with reload set to TRUE.

   // getting the matched route
   $matched = $app->router()->getMatchedRoutes('GET','/classes/name', true);

   // dispatching the (first) matched route
   $matched[0]->dispatch(); 

Here you might want to add some checks and for example dispatch notFound in case no route is matched. I hope you get the idea =)

like image 139
Martin Turjak Avatar answered Oct 17 '22 15:10

Martin Turjak


There is redirect() method. However it sends an 302 Temporary Redirect response which you do not want.

$app->get("/foo", function () use ($app) {
    $app->redirect("/bar");
});

Another possibility is pass() which tells application to continue to next matching route. When pass() is called Slim will immediately stop processing the current matching route and invoke the next matching route.

If no subsequent matching route is found, a 404 Not Found is sent to the client.

$app->get('/hello/foo', function () use ($app) {
    echo "You won't see this...";
    $app->pass();
});

$app->get('/hello/:name', function ($name) use ($app) {
    echo "But you will see this!";
});
like image 27
Mika Tuupola Avatar answered Oct 17 '22 14:10

Mika Tuupola