无法将属性从一个中间件传递到下一个

Can't pass attributes from one middleware to the next

两个中间件都是路由组中间件,调用代码如下:

$this->get( '/edit/{id}', \Rib\Src\Apps\Blog\BlogControllers\EditController::class . ':index' )
     ->add( new RequireAuth() )
     ->add( new RequireOwner() );

中间件 1,请看最后两行,我在其中设置了中间件属性,就像在 slim 站点上一样:

use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;

/**
 * MiddleWare that insures that the user accessing a resource is authenticated.
 * Class RequireAuth
 * @package Rib\Src\MiddleWares
 */
class RequireAuth
{

    # Variable used to disable redirect to '/user/set-username' from itelf. That would cause infinite redirection loop.
    # This is passed to the middleWare from the list of routes. Of course only true for '/user/set-username' pages.
    private $disableUserNameValidationCheck;


    function __construct( $disableUserNameValidationCheck = false )
    {
        $this->disableUserNameValidationCheck = $disableUserNameValidationCheck;
    }


    public function __invoke( Request $request, Response $response, $next )
    {
        # User is not authenticated: we ensure this by checking his id which is necessarily set when he is logged in.
        if ( ! isset( $_SESSION[ 'id' ] ) ) {
            FlashMessages::flashIt( 'message', "The page you tried to access requires that you are logged in the site." );

            return $response->withRedirect( '/user/login' );
        }

        # In case user has logged in from a social network and has not set a user name and password. Username is 'temporary-.....'
        # We really want the user to set his username. So on designated page we force redirect to page to setup username and email.
        if ( ! $this->disableUserNameValidationCheck and isset( $_SESSION[ 'username' ] ) and strpos( $_SESSION[ 'username' ], 'temporary' ) !== false ) {
            FlashMessages::flashIt( 'message',
                "This part of the site requires that you complete your profile with a definitive username and email. Thank you for your understanding." );

            return $response->withRedirect( '/user/set-username' );
        }

        # Set in request some data so it won't be needed to fetch it from the other potential middlewares in the chain
        $request = $request->withAttribute( 'foo', 'bar' );

        # Process regular flow if not interrupted by the middleWare.
        return $next( $request, $response );
    }
}

应该获取属性的中间件 2:

use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;

class RequireOwner
{
    public function __invoke( Request $request, Response $response, $next )
    {
        $foo = $request->getAttribute( 'foo' ); // null


        return $next( $request, $response );
    }

}

为什么第二个中间件的 foo 值为 null 而不是 bar ?

中间件是后进先出执行的。要执行 RequireAuth 首先更改添加中间件的顺序。

$this->get('/edit/{id}', \Rib\Src\Apps\Blog\BlogControllers\EditController::class . ':index')
     ->add(new RequireOwner())
     ->add(new RequireAuth());