导致getArguments()为null的中间件

时间:2017-04-24 09:52:45

标签: php slim

以下是中间件流程:

# Post edit
$this->get( '/edit/{id}/{slug}', \Rib\Src\Apps\Post\PostControllers\EditController::class . ':index' )
     ->add( new EnforceEditDelay() )
     ->add( new RequireOwner( 'posts' ) )
     ->add( new RejectBanned() )
     ->add( new RequireAuth() );

->add( new RejectBanned() )导致链中的下一个中间件断开:

'Call to a member function getArguments() on null'

RequireAuth():

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 )
    {
        $session = $_SESSION;

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

        $request = $request->withAttribute( 'session', $session );
        # Process regular flow if not interrupted by the middleWare.
        return $next( $request, $response );
    }

}

RejectBanned():

class RejectBanned
{
    /**
     * Reject banned user
     * @param Request $request
     * @param Response $response
     * @param $next
     * @return Response
     */
    public function __invoke( Request $request, Response $response, $next )
    {
        $session = $request->getAttribute( 'session' ) ?? null;

        # Get usergroup from db
        $user = ( new DbSql() )->db()->table( 'users' )->find( $session['id'] );
        $userGroup = $user->user_group;

        # Store it in session
        $session['user_group'] = $userGroup;

        # Redirect user if usergroup = banned
        if ( $userGroup === 'banned' ) {
            FlashMessages::flashIt( 'message', 'You are not allowed anymore to access this resource.' );

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

        # Store info for the next middleware or controller
        $request = $request->withAttributes( [ 'session' => $session ] );

        # User is not banned, pursue
        return $next( $request, $response );
    }
}

RequireOwner()(这是它中断的地方,我在其中断的地方添加了注释):

class RequireOwner
{
    private $table;


    function __construct( $tableName )
    {
        $this->table = $tableName;
    }


    public function __invoke( Request $request, Response $response, $next )
    {
        $session = $request->getAttribute( 'session' ) ?? null;
        // BREAKS HERE:
        $recordId = $request->getAttribute( 'route' )->getArguments()[ 'id' ] ?? null; // BREAKS HERE
        $currentUserGroup = $session[ 'user_group' ] ?? null;
        $currentUserId = $session[ 'id' ] ?? null;

        $recordInstance = ( new DbSql() )->db()->table( $this->table )->find( $recordId );

        # If any info is missing, interrupt
        if ( ! $recordInstance or ! $session or ! $recordId or ! $currentUserGroup or ! $currentUserId ) {
            throw new Exception( 'Missing information to determine the owner of record' );
        }

        # Store info for the next middleware or controller
        $request = $request->withAttributes( [ 'session' => $session, 'recordInstance' => $recordInstance ] );

        # User is an Admin, he can edit any post
        if ( $currentUserGroup === 'admin' ) {
            return $next( $request, $response );
        }

        # User is not owner of post
        if ( $currentUserId != $recordInstance->author_id ) {
            FlashMessages::flashIt( 'message', 'You must be the author of this content to be able to edit it.' );

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

        # User is not admin but is owner of content
        return $next( $request, $response );
    }

}

那么为什么->add( new RejectBanned() )会在下一个中间件中导致空值?

1 个答案:

答案 0 :(得分:0)

在RejectBanned()中:

$request = $request->withAttributes( [ 'session' => $session ] );

$request = $request->withAttribute( 'session', $session );

它解决了这个问题。