Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FOSUserBundle overriding incoherence

I've come across countless questions about FOSUserBundle's overriding possibilities, and discovered some "design incoherence" in their use of Twig's inheritance mechanisms, which I'd like to clarify as it is really disturbing in some projects...

Overriding a template in FOSUserBundle

From what I've read, here's how we should override a template. Let's say, the login template (Security/login.html.twig). First, I need to override the global FOSUser layout (layout.html.twig').

Global FOSUser layout

{% extends "::layout.html.twig" %}
{% block title %}Page title{% endblock title %}
{% block body %}
    <div id="container">
       {% block fos_user_content %}{% endblock %}
    </div>
{% endblock body %}

The title and body blocks are references to the HTML <title> and <body> tags (globally). Now, when it comes to the login itself, here's what I've written.

Login form

{% extends "MyUserBundle::layout.html.twig" %}

{% block fos_user_content %}
    {% if error %}
        <div class="error">{{ error|trans({}, 'FOSUserBundle') }}</div>
    {% endif %}
    <form action="{{ path("fos_user_security_check") }}" method="post">
        <input type="hidden" name="_csrf_token" value="{{ csrf_token }}" />
        <label for="username">{{ 'security.login.username'|trans({}, 'FOSUserBundle') }}</label>
        <input type="text" id="username" name="_username" value="{{ last_username }}" required="required" /><br />
        <label for="password">{{ 'security.login.password'|trans({}, 'FOSUserBundle') }}</label>
        <input type="password" id="password" name="_password" required="required" /><br />
        <input type="checkbox" class="checkbox" id="remember_me" name="_remember_me" value="on" />
        <label for="remember_me">{{ 'security.login.remember_me'|trans({}, 'FOSUserBundle') }}</label><br />
        <label for="_submit"></label>
        <input type="submit" class="submit" id="_submit" name="_submit" value="{{ 'security.login.submit'|trans({}, 'FOSUserBundle') }}" />
    </form>
{% endblock fos_user_content %}

Now, here's what I automatically understand : the layout creates an environment, and other templates are "included" into the fos_user_content block. The result for the login page follows this scheme.

Another try ? Registration.

Now, following this pattern, I tried to extend the registration form thinking : "I should extend the content of the fos_user_content just like I did before! Guess what? That's not it! Here's my Registration/register_content.html.twig file.

Register form content

{% extends "MyUserBundle::layout.html.twig" %}

{% block fos_user_content %}
    <form action="{{ path('fos_user_registration_register') }}" {{ form_enctype(form) }} method="POST" class="fos_user_registration_register">
        {{ form_widget(form) }}
        <div>
            <input type="submit" value="{{ 'registration.submit'|trans({}, 'FOSUserBundle') }}" />
        </div>
    </form>
{% endblock %}

Problem

The previous pattern does not seem to apply to the Registration part : when I follow the same scheme, my registration page is graphically doubled. The form is printed twice, the titles as well, and so on... Just like I had done a unnecessary include/inheritance somewhere...

Does anyone have any idea with FOSUserBundle isn't designed with a universal pattern for overriding templates ? Why do I need to rebuild the complete inheritance tree to have a similar display on both the login, and the registration form ?

Solution (?)

Cerad's answer gives a different scheme for the registration case. The Twig inheritance tree excludes register_content.html.twig, and uses register.html.twig. When you have a look at this file, you can see it simply... includes register_content.html.twig. This is the incoherence I'm talking about. Why is this ? Why not use a single file with the content, directly ? Why is it that FOS decided to add this useless (?) include step ?

like image 219
John WH Smith Avatar asked Nov 02 '22 06:11

John WH Smith


1 Answers

I'm not entirely sure I understand your question. register_content.html.twig is designed to be included by register.html.twig and thus has no extends statement in it. It is register.html.twig that contains the extends statement. Not sure if that will help your problem or not.

Update: So why did they do it this way?

Of course you will have the ask the authors to really know. All I can do is speculate.

It's possible to setup template inheritance such that FOSUserBundle::layout.html.twig can be overridden with your own layout file without editing changing or copying the FOSUserBundle templates. I won't try to go into the details of how to do this. I suspect you have already tried.

Using the same technique, you can replace the FOSUserBundle register_contents template with your own. That lets you customize the contents of your registration page without really worrying about exactly how it gets included.

Personally, I found the whole bundle to be messy. I copied out some of the user entity and manager stuff to my own user bundle. I ignored their templates and controllers. If a stable version is ever released which targets S2.1 or above then I might revisit the bundle. But it's been years since S2.1 was released and there is still no stable version available.

My advice: if the templates are bugging you then don't use them.

like image 199
Cerad Avatar answered Nov 13 '22 22:11

Cerad