Symfony2 fos登录,注册和忘记密码在一个视图中

2022-01-22 00:00:00 php symfony twig fosuserbundle

我需要将购买的模板应用到我们的仪表板.在此模板中,登录、注册和忘记密码表单都在同一个视图下,并使用简单的JQuery在它们之间切换.

我一直在寻找一种将所有三种形式合二为一的好方法、不太浮夸的方法,但我一无所获.

我的常备选项(如我所见),以及为什么我不喜欢其中任何一个:

  1. 从 fos 包中获取视图,将它们复制到 /app/Resources/FOSUserBundle/views/,删除 {% extend %} 部分和 {% include %} 在我自己的登录视图中.不喜欢的原因:在我看来,这有点像一个快速的-n-dirty 修复 - 那部分不起作用?让我们中断它吧!":)
  2. 扩展 fos 包,在 LoginActionRegisterAction 中接受一个额外的参数,在我自己的参数中使用 {% render %}登录视图.不喜欢的原因:扩展整个包并修改两个不同的控制器只是为了改变它的呈现方式感觉就像糟糕的 MVC.
  3. XHR 加载所有内容.不喜欢的原因:这种方法在使用内页时是有意义的,但对于无论如何都要重新加载的页面就没有意义了.

TL;DR 版本:我正在寻找一种在一个页面中包含登录、注册和忘记密码表单的非黑客方式.

任何帮助将不胜感激!

解决方案

我找到了一个适合我当前项目的解决方案.预先提出的解决方案的优缺点:

优点:

  • 需要实施的 LOC 很少
  • FOSUserBundle 更新证明(不覆盖视图脚本*)

缺点:

  • 子请求导致的性能开销
  • 只能显示表单,表单提交(以及随后提交时的错误处理)将始终转到 FOSUserBundle 提供的页面
  • 仍然感觉像是一个快速修复,但比其他选项更好

* 只需要覆盖 layout.html.twig 文件

<小时>

话虽如此,这就是我所做的:

  1. 在模板中呈现表单
    使用 嵌入式控制器 呈现您需要的表单:

    <h2>登录</h2>{{ render(controller('FOSUserBundle:Security:login', { embeddedForm: true})) }}</div>

    <h2>重置</h2>{{ render(controller('FOSUserBundle:Resetting:request', { embeddedForm: true})) }}</div>

  2. 覆盖 FOSUserBundle 布局
    当我使用捆绑提供的路由时,我必须 覆盖 FOSUserBundle 布局模板文件 以扩展我的应用程序的标准布局.由于覆盖的 FOSUserBundle 布局文件扩展了主应用程序布局文件,因此每次调用 {{ render ... }} 都会重复布局.为了防止这种情况,我们需要动态解除扩展布局文件.这是覆盖的布局文件的样子:

    {# app/Resources/FOSUserBundle/views/layout.html.twig #}{% if app.request.get('embeddedForm') %}{% 设置布局 = 'AcmeBundle::layout-content.html.twig' %}{% 别的 %}{% 设置布局 = 'AcmeBundle::layout.html.twig' %}{%  万一 %}{% 扩展布局 %}{% 块内容 %}{% 块 fos_user_content %}{% endblock %}{% 端块 %}

  3. 创建 AcmeBundle::layout-content.html.twig 文件
    这种布局应该只呈现 FOSUserBundle 视图脚本的 content 块,并且非常简短:

    {# src/Acme/DemoBundle/Resources/views/layout-content.html.twig #}{% 块内容 %}{% endblock %}

现在表单将很好地呈现所有依赖项(CSRF 等).但是,提交表单会将您带到 FOSUserBundle 操作.

<小时>

替代解决方案:

  • 这个答案描述了如何手动实现表单并将它们链接到 FOSUserBundle 控制器.

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:

  1. 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!" :)
  2. Extend the fos bundle, accept an extra parameter in the LoginAction and RegisterAction, 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.
  3. 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!

解决方案

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:

  1. 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>
    

  2. 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 %}
    

  3. Create the AcmeBundle::layout-content.html.twig file
    This layout should only render the content 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.

相关文章