问题
I need to apply a purchased template to our dashboard. In this template, the login, register and forgot password forms are all under the same view, and switching between them using simple JQuery.
I have been looking for a nice, not-too-flashy way of combining all three forms into one, but I came up empty.
My standing options (as I see them), and why I don't like any of them:
- Take the views from the fos bundle, copy them to
/app/Resources/FOSUserBundle/views/
, remove the{% extend %}
part and{% include %}
them in my own login view. Reason for dislike: to me this looks a little like a quick-n-dirty fix - "that part's not working? Let's break it off!" :) - Extend the fos bundle, accept an extra parameter in the
LoginAction
andRegisterAction
, use{% render %}
with parameters in my own login view. Reason for dislike: extending a whole bundle and modifying two different controllers just to change the way it renders feels like bad MVC. - XHR load everything. Reason for dislike: this approach makes sense when using inner pages, but for pages that reload anyway it just doesn't make sense.
TL;DR version: I'm looking for a non-hack way of including the login, register and forgot password form in one page.
Any help would be greatly appreciated!
回答1:
I found a solution with which I am comfortable with for my current project. The advantages and disadvantages of the proposed solution upfront:
Advantages:
- few LOC to implement
- FOSUserBundle update proof (does not override the view scripts*)
Disadvantages:
- performance overhead due to subrequests
- only forms can be displayed, form submission (and subsequently error handling upon submission) will always go to the pages provided by FOSUserBundle
- still feels like a quick-n-dirty fix, but better than other options
* only needs to override the layout.html.twig file
With that being said, here is what I have done:
Render the form in your template
Use embedded controllers to render the forms you need:<div> <h2>Login</h2> {{ render(controller('FOSUserBundle:Security:login', { embeddedForm: true})) }} </div> <div> <h2>Reset</h2> {{ render(controller('FOSUserBundle:Resetting:request', { embeddedForm: true})) }} </div>
Override FOSUserBundle layout
As I use the routes provided by the bundle, I had to override the FOSUserBundle layout template file to extend the standard layout of my application. As the overriden FOSUserBundle layout file extends the main applications layout file the layout would be repeated for each call{{ render ... }}
. To prevent that, we need to dynamically disarm the extended layout file. Here is what the overriden layout file looks like:{# app/Resources/FOSUserBundle/views/layout.html.twig #} {% if app.request.get('embeddedForm') %} {% set layout = 'AcmeBundle::layout-content.html.twig' %} {% else %} {% set layout = 'AcmeBundle::layout.html.twig' %} {% endif %} {% extends layout %} {% block content %} {% block fos_user_content %}{% endblock %} {% endblock %}
Create the
AcmeBundle::layout-content.html.twig file
This layout should only render thecontent
block of the FOSUserBundle view scripts and is such short and simple:{# src/Acme/DemoBundle/Resources/views/layout-content.html.twig #} {% block content %}{% endblock %}
Now the forms will render nicely with all dependencies (CSRF and so forth). Submitting the form will however take you to the FOSUserBundle actions.
Alternative solution:
- This answer describes how to manually implement the forms and link them to the FOSUserBundle controller.
来源:https://stackoverflow.com/questions/26959973/symfony2-fos-login-register-and-forgot-password-in-one-view