从苗条中间件重定向的正确方法
Proper way to redirect from slim middleware
目标是将用户从中间件重定向到登录页面。
中间件是从带有以下行的苗条路由组调用的:
$this->get( '/profile', ProfileController::class . ':index' )->add( new RequireLogin() );
这是中间件
<?php
namespace Rib\Src\MiddleWares;
use Rib\Src\Services\FlashMessages;
use Slim\Http\Request;
use Slim\Http\Response;
class RequireLogin
{
/**
* Example middleware invokable class
*
* @param \Psr\Http\Message\ServerRequestInterface $request PSR7 request
* @param \Psr\Http\Message\ResponseInterface $response PSR7 response
* @param callable $next Next middleware
*
* @return \Psr\Http\Message\ResponseInterface
*/
public function __invoke( $request, $response, $next )
{
if ( ! isset( $_SESSION[ 'id' ] ) ) {
FlashMessages::flashIt( 'message', "The page you tried to access requires an active session. Please log back in." );
header( 'Location: /user/login' ); # THIS LINE
exit; # AND THIS ONE
}
$response = $next( $request, $response );
return $response;
}
}
我的目标是当中间件检测到用户当前未登录时,将用户重定向到登录页面。
您可以看到我当前的方式是错误的:我使用重定向后跟退出。
如何用正确的 "slim" 方式替换这两行?
Response
有个好用的方法withRedirect()
,你可以这样使用:
<?php
if (!isset($_SESSION[ 'id' ])) {
FlashMessages::flashIt( 'message', "The page you tried to access requires an active session. Please log back in." );
$url = '/user/login';
return $response->withRedirect($url);
} else {
return $next($request, $response);
}
但是仍然存在一个问题:您正在硬编码 URL 您希望将未经身份验证的用户重定向到的位置。考虑通过它的名称获取 URL(你可以在声明路由时给出):
<?php
// Add unique name to the route so you can
// refer to it later in the code (this is what we're going to do now)
$app->get('/user/login', YourController::class)->setName('userLoginPage');
现在您可以通过名称引用该路由,而不是中间件中的 URL 本身。为此,您需要注入 Slim Router 对象:
<?php
namespace Rib\Src\MiddleWares;
use Rib\Src\Services\FlashMessages;
use Slim\Http\Request;
use Slim\Http\Response;
use Slim\Router;
class RequireLogin
{
/**
* Object constructor
*
* Inject Slim Router here, so you can access route names.
*
* @param Router $router
*/
public function __construct(Router $router)
{
$this->router = $router;
}
/**
* Example middleware invokable class
*
* @param \Psr\Http\Message\ServerRequestInterface $request PSR7 request
* @param \Psr\Http\Message\ResponseInterface $response PSR7 response
* @param callable $next Next middleware
*
* @return \Psr\Http\Message\ResponseInterface
*/
public function __invoke( $request, $response, $next )
{
if ( ! isset( $_SESSION[ 'id' ] ) ) {
FlashMessages::flashIt( 'message', "The page you tried to access requires an active session. Please log back in." );
// Get url by name: this is more flexible than hardcoding URL
$url = $this->router->pathFor('userLoginPage') . ' #forbidden';
return $response->withRedirect($url);
} else {
return $next( $request, $response );
}
}
}
这里的好处是,当您更改用户登录页面的实际 URL 时,您不必在中间件中更改它,因为它是通过 $router->pathFor()
方法访问的。
我会说这是非常苗条的好方法。 )
目标是将用户从中间件重定向到登录页面。 中间件是从带有以下行的苗条路由组调用的:
$this->get( '/profile', ProfileController::class . ':index' )->add( new RequireLogin() );
这是中间件
<?php
namespace Rib\Src\MiddleWares;
use Rib\Src\Services\FlashMessages;
use Slim\Http\Request;
use Slim\Http\Response;
class RequireLogin
{
/**
* Example middleware invokable class
*
* @param \Psr\Http\Message\ServerRequestInterface $request PSR7 request
* @param \Psr\Http\Message\ResponseInterface $response PSR7 response
* @param callable $next Next middleware
*
* @return \Psr\Http\Message\ResponseInterface
*/
public function __invoke( $request, $response, $next )
{
if ( ! isset( $_SESSION[ 'id' ] ) ) {
FlashMessages::flashIt( 'message', "The page you tried to access requires an active session. Please log back in." );
header( 'Location: /user/login' ); # THIS LINE
exit; # AND THIS ONE
}
$response = $next( $request, $response );
return $response;
}
}
我的目标是当中间件检测到用户当前未登录时,将用户重定向到登录页面。 您可以看到我当前的方式是错误的:我使用重定向后跟退出。
如何用正确的 "slim" 方式替换这两行?
Response
有个好用的方法withRedirect()
,你可以这样使用:
<?php
if (!isset($_SESSION[ 'id' ])) {
FlashMessages::flashIt( 'message', "The page you tried to access requires an active session. Please log back in." );
$url = '/user/login';
return $response->withRedirect($url);
} else {
return $next($request, $response);
}
但是仍然存在一个问题:您正在硬编码 URL 您希望将未经身份验证的用户重定向到的位置。考虑通过它的名称获取 URL(你可以在声明路由时给出):
<?php
// Add unique name to the route so you can
// refer to it later in the code (this is what we're going to do now)
$app->get('/user/login', YourController::class)->setName('userLoginPage');
现在您可以通过名称引用该路由,而不是中间件中的 URL 本身。为此,您需要注入 Slim Router 对象:
<?php
namespace Rib\Src\MiddleWares;
use Rib\Src\Services\FlashMessages;
use Slim\Http\Request;
use Slim\Http\Response;
use Slim\Router;
class RequireLogin
{
/**
* Object constructor
*
* Inject Slim Router here, so you can access route names.
*
* @param Router $router
*/
public function __construct(Router $router)
{
$this->router = $router;
}
/**
* Example middleware invokable class
*
* @param \Psr\Http\Message\ServerRequestInterface $request PSR7 request
* @param \Psr\Http\Message\ResponseInterface $response PSR7 response
* @param callable $next Next middleware
*
* @return \Psr\Http\Message\ResponseInterface
*/
public function __invoke( $request, $response, $next )
{
if ( ! isset( $_SESSION[ 'id' ] ) ) {
FlashMessages::flashIt( 'message', "The page you tried to access requires an active session. Please log back in." );
// Get url by name: this is more flexible than hardcoding URL
$url = $this->router->pathFor('userLoginPage') . ' #forbidden';
return $response->withRedirect($url);
} else {
return $next( $request, $response );
}
}
}
这里的好处是,当您更改用户登录页面的实际 URL 时,您不必在中间件中更改它,因为它是通过 $router->pathFor()
方法访问的。
我会说这是非常苗条的好方法。 )