I'm trying to embed all FOSUserBundle forms in a sidebar on the left of my layout.

Here's my src/My/MainBundle/Resources/config/routing.yml:

index:
    pattern: /
    defaults: { _controller: MyMainBundle:Main:index }

login:
    pattern: /login
    defaults: { _controller: MyMainBundle:Main:index }

resetting_request:
    pattern: /resetting/request
    defaults: { _controller: MyMainBundle:Main:index }

resetting_send_email:
    pattern: /resetting/send-email
    defaults: { _controller: MyMainBundle:Main:index }

In src/My/MainBundle/Resources/views/layout.html.twig, I have (among other things):

<div id="sidebar">
    {% if is_granted('IS_AUTHENTICATED_REMEMBERED') %}
        <p>You are logged in blah blah blah</p>
    {% elseif app.request.attributes.get('_route') == 'resetting_request' %}
        {{ render(controller('FOSUserBundle:Resetting:request')) }}
    {% elseif app.request.attributes.get('_route') == 'resetting_send_email' %}
        {{ render(controller('FOSUserBundle:Resetting:sendEmail')) }}
    {% else %}
        {{ render(controller('FOSUserBundle:Security:login')) }}
    {% endif %}
</div>

The login form works fine, it submits to /login_check, which then redirects to the page that was requested, if the login and password are correct, or, it redirects to /login if the login or password are wrong (in that case it correctly displays the form in the sidebar, with the corresponding error message).

I'm having trouble with the "Forgot password?" form, though.

It shows up in the sidebar, and submits to /resetting/send-email, but then it doesn't redirect to anything. It then tells me that the username or email "" doesn't exist.

If I comment the "resetting_send_email" route, then the "send email" action works, but the output is not in the sidebar (in fact, there isn't even a layout around it).

Any ideas?

有帮助吗?

解决方案 2

I tried using controller events, but it wasn't enough.

I had to override the FOSUserBundle controllers.

So, I created a new bundle (MyUserBundle), child of FOSUserBundle, as explained in the link, and here's my controller:

// src/My/UserBundle/Controller/ResettingController.php

namespace My\UserBundle\Controller;

use \Symfony\Component\HttpFoundation\Request;
use FOS\UserBundle\Controller\ResettingController as BaseController;
use Symfony\Component\HttpFoundation\RedirectResponse;

class ResettingController extends BaseController
{
    /**
     * Request reset user password: submit form and send email
     */
    public function sendEmailAction(Request $request)
    {
        //$username = $request->request->get('username'); // Since this action was called in a twig file by a "{{ render(controller(...)) }}", the "request" attribute is empty.
        $username = $_POST['username']; // But $_POST still works

        /** @var $user UserInterface */
        $user = $this->container->get('fos_user.user_manager')->findUserByUsernameOrEmail($username);

        if (null === $user) {
            return $this->container->get('templating')->renderResponse('FOSUserBundle:Resetting:request.html.'.$this->getEngine(), array('invalid_username' => $username));
        }

        if ($user->isPasswordRequestNonExpired($this->container->getParameter('fos_user.resetting.token_ttl'))) {
            return $this->container->get('templating')->renderResponse('FOSUserBundle:Resetting:passwordAlreadyRequested.html.'.$this->getEngine());
        }

        if (null === $user->getConfirmationToken()) {
            /** @var $tokenGenerator \FOS\UserBundle\Util\TokenGeneratorInterface */
            $tokenGenerator = $this->container->get('fos_user.util.token_generator');
            $user->setConfirmationToken($tokenGenerator->generateToken());
        }

        $this->container->get('fos_user.mailer')->sendResettingEmailMessage($user);
        $user->setPasswordRequestedAt(new \DateTime());
        $this->container->get('fos_user.user_manager')->updateUser($user);

        //return new RedirectResponse($this->container->get('router')->generate('fos_user_resetting_check_email',
        //    array('email' => $this->getObfuscatedEmail($user))
        //)); // Throws an exception (because this action was called by a "{{ render(controller(..)) }}").

        //header('Location: '.$this->container->get('router')->generate('fos_user_resetting_check_email', array('email' => $this->getObfuscatedEmail($user))));
        //exit; // The redirect works, but the "exit" prevents the email from being sent

        return new \Symfony\Component\HttpFoundation\Response(
            '<script type="text/javascript">window.location = "'.$this->container->get('router')->generate('fos_user_resetting_check_email', array('email' => $this->getObfuscatedEmail($user))).'"</script>'
        );
    }
}

In my layout.html.twig, I replaced

{{ render(controller('FOSUserBundle:Resetting:sendEmail')) }}

by

{{ render(controller('MyUserBundle:Resetting:sendEmail')) }}

I'm now going to embed the "check_email" action in my sidebar, as well as the other forms/templates from the FOSUserBundle.

其他提示

FOSUserBundle:Resetting:sendEmail is expecting the username or email as a POST.

public function sendEmailAction(Request $request)
{
    $username = $request->request->get('username');

    /** @var $user UserInterface */
    $user = $this->container->get('fos_user.user_manager')
                ->findUserByUsernameOrEmail($username);

    if (null === $user) {
        return $this->container->get('templating')->renderResponse('bla blah');
    }

When you render the controller you make new request to the controller with no POST so there is no email or username.

With no POST the script can't find a user which means it breaks at that first check.

Isn't it simplest to comment

    <requirement key="_method">POST</requirement>

into

    <!-- <requirement key="_method">POST</requirement> --> 

in /Resources/config/routing/resetting.xml ?

Since the only information passed is the username (which is available in public anyway) I "hope" that I am not exposing myself to a hidden risk here.

I have the same issue and the commenting did the trick (thanks to user's 3409662 comments).

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top