Slim 3 Middleware Redirect
Asked Answered
L

4

9

I want to check if a user is logged in. Therefor I have an Class witch returns true or false. Now I want a middleware which checks if the user is logged in.

$app->get('/login', '\Controller\AccountController:loginGet')->add(Auth::class)->setName('login');
$app->post('/login', '\Controller\AccountController:loginPost')->add(Auth::class);

Auth Class

class Auth {
    protected $ci;
    private $account;

    //Constructor
    public function __construct(ContainerInterface $ci) {
        $this->ci = $ci;
        $this->account = new \Account($this->ci);
    }

    public function __invoke($request, \Slim\Http\Response $response, $next) {
        if($this->account->login_check()) {
            $response = $next($request, $response);
            return $response;
        } else {
            //Redirect to Homepage
        }

    }
}

So when the user is logged in the page will render correctly. But when the user is not autoriesed I want to redirect to the homepage. But how?!

$response->withRedirect($router->pathFor('home');

This doesn't work!

Latona answered 9/4, 2016 at 18:53 Comment(0)
G
10

You need to return the response. Don't forget that the request and response objects are immutable.

return $response = $response->withRedirect(...);

I have a similar auth middleware and this is how I do it which also adds a 403 (unauthorized) header.

$uri = $request->getUri()->withPath($this->router->pathFor('home'));
return $response = $response->withRedirect($uri, 403);
Gipon answered 9/4, 2016 at 21:51 Comment(1)
In OP's case, they didn't define a $router variable before using it. Where do you define $this->router assuming your Middleware didn't inherit from another class?Tracee
M
3

Building off of tflight's answer, you will need to do the following to make everything work as intended. I tried to submit this as a revision, given that the code provided in tflight's answer would not work on the framework out of the box, but it was declined, so providing it in a separate answer:

You will need the following addition to your middleware:

protected $router;

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

Additionally, when declaring the middleware, you would need to add the following the constructor:

$app->getContainer()->get('router')

Something similar to:

$app->add(new YourMiddleware($app->getContainer()->get('router')));

Without these changes, the solution will not work and you will get an error that $this->router does not exist.

With those changes in place you can then utilize the code provided by tflight

$uri = $request->getUri()->withPath($this->router->pathFor('home'));
return $response = $response->withRedirect($uri, 403);
Myrticemyrtie answered 21/4, 2017 at 18:11 Comment(0)
T
0

make basic Middleware and inject $container into it so all your middleware can extends it.

Class Middleware
{
  protected $container;

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

  public function __get($property)
  {
    if (isset($this->container->{$property})) {
      return $this->container->{$property};
    }
    // error
  }
}

make sure your Auth middleware on the same folder with basic middleware or you can use namespacing.

class Auth extends Middleware
{
  public function __invoke($request, $response, $next)
  {
    if (!$this->account->login_check()) {
      return $response->withRedirect($this->router->pathFor('home'));
    }

    return $next($request, $response);
  }
}
Thomasinathomasine answered 4/10, 2018 at 11:37 Comment(0)
G
-1

Use:

http_response_code(303);
header('Location: ' . $url);
exit;
Geneva answered 6/12, 2016 at 13:19 Comment(8)
Please try to explain your answer instead of just posting code.Trinh
@NahuelIanni, it is self-explanatory if you know PHP.Geneva
While I'm sure this probably works, OP was probably looking for a solution that used the functionality of the Slim Framework, instead of plain PHP.Tracee
@KimberlyW I could not find anything built-in that worked from within middleware.Geneva
Yes this is a solution, but not a proper one.Pistole
@aod, what is the proper one?Geneva
@systemovich you can see above.Pistole
While maybe not pretty, it's easy to read and avoids the craziness of having to bubble up through the middleware keeping track of whether or not the redirect is a response. The complexity of redirects inside middleware, with Slim, comes from the fact that you shouldn't run the inner layer of the middleware, or the redirect won't work.Briggs

© 2022 - 2024 — McMap. All rights reserved.