将Symfony2 LogoutSuccessHandler重定向到原始注销目标

I need to modify my user object on logout. To do this, I have a security.yml that contains the following (amongst other things) -

#...
    logout:
        success_handler: my.logout_success_handler
        target: /
#...

...this defines a logout success handler, which is defined in services.yml like this -

   my.security.logout_success_handler:
       class: My\Security\LogoutSuccessHandler
       arguments: ["@security.context", "@doctrine.orm.default_entity_manager"]

...finally, the business-end of my handler is like this -

// ...
public function onLogoutSuccess(Request $request)
{

    $user = $this->securityContext->getToken()->getUser();

    // ... do stuff with the user object....
    $this->em->flush();

    // now what?

}
// ...

So, where it says "now what?" I understand that I need to return a Response object. Ideally I want that response object to redirect the user to whatever is defined in logout.target in the security.yml.

Is there an easy way I can query that? Or, even better, is there another way of doing this kind of thing that doesn't require me to get involved with the request/response objects at all?

Thanks

So, I think I've figured out the right answer -

Rather than implementing LogoutSuccessHandlerInterface and configuring a logout.success_handler, my security.yml now looks like this -

# ...
logout:
    handlers: [my.bundle.security.logout_handler]
# ...

...and I'm implementing Symfony\Component\Security\Http\Logout\LogoutHandlerInterface. Confusing naming, but this seems to be the preferred way of doing post-logout operations without having to get involved with the response object. My implementation looks like this -

namespace My\Bundle\Security;

use Symfony\Component\Security\Http\Logout\LogoutHandlerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\ORM\EntityManager;

/**
 * Do post logout stuff
 */
class LogoutHandler implements LogoutHandlerInterface
{

    /**
     * @var EntityManager
     */
    protected $em;

    /**
     * Constructor
     * @param EntityManager $em
     */
    public function __construct(EntityManager $em)
    {

        $this->em = $em;
    }

    /**
     * Do post logout stuff
     */
    public function logout(Request $request, Response $response, TokenInterface $authToken)
    {
        $user = $authToken->getUser();

        // do stuff with the user object...
        $this->em->flush();

        return $response;
    }
}

...as you can see, the LogoutHandlerInterface provides a pre-made $response object that I can just return when I'm finished.

You could define your target as a parameter in your parameters.yml or config.yml:

parameters:
    logout.target: /

And then reference this value in your security.yml:

    logout:
        success_handler: my.logout_success_handler
        target: %logout.target%   

And/or inject it into your logout handler:

    my.security.logout_success_handler:
        class: My\Security\LogoutSuccessHandler
        arguments: ["@security.context", "@doctrine.orm.default_entity_manager", %logout.target%]

And return a RedirectResponse with this value:

// Assign the 3. constructor parameter to the instance variable $logoutTarget

public function onLogoutSuccess(Request $request)
{
    // ...

    return new RedirectResponse($this->logoutTarget);
}

You could use composition and inject the default LogoutSuccessHandler into your object and call the onLogoutSucces method on it.

The following pseudu code shows the idea of doing it.

class MyLogoutSuccessHandler implements \LogoutSuccessHandler
{
    protected $original;

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

    public function onLogoutSuccess(Request $request)
    {
        // do stuf your want and delegate to the original
        return $this->original->onLogoutSuccess($request);
    }
}

This is also the way HttpKernelInterface works in StackPHP and when you use HttpCache in your application.

Hopefully this helps, happy coding :)