gstreamer0.10-ffmpeg
gstreamer0.10-plugins-good
packages.
Everything works, but if you go to /register
... it looks awful. Well, of course it looks awful! FOSUserBundle has no idea how the page should be styled. But don't worry: we can get this looking much better, very quickly.
First, on the web debug toolbar, find the template icon and click it. This will show you all the templates used to render this page... which is a beautiful cheat sheet for knowing what templates you can override!
The one I'm interested in is layout.html.twig
, which lives in FOSUserBundle.
In my editor, I'll press Shift+Shift to open that file. Ok, every Twig template in FOSUserBundle extends this layout.html.twig
file. For example, see the "Logged in as" text? That's coming from here.
But, we want all of FOSUserBundle's templates to instead extend our base.html.twig
template. How can we do that?
By overriding layout.html.twig
. Let's see how. First, to override any template from a bundle, just go to app/Resources
, then create a directory with the same name as the bundle: FOSUserBundle
. Inside, create one more directory: views
.
Tip
The location where templates should live to override bundle templates has changed in Symfony 4. But, the idea is still the same. For details, see: https://symfony.com/blog/new-in-symfony-3-4-improved-the-overriding-of-templates.
In this case, the layout.html.twig
template lives right the root of the views/
directory in the bundle. So that's where we need to create our's. Inside, extend the normal base.html.twig
.
{% extends 'base.html.twig' %} | |
... lines 2 - 6 |
Here's the magic part. Hit Shift+Shift again and open register.html.twig
: this is the template for the registration page. Notice that it overrides a block called fos_user_content
. In layout.html.twig
, this is printed in the middle.
So check this out: inside of our version of layout.html.twig
, add {% block body %}
: that's the name of the block in our base.html.twig
. Then, include {% block fos_user_content %}
and {% endblock %}
.
{% extends 'base.html.twig' %} | |
{% block body %} | |
{% block fos_user_content %}{% endblock %} | |
{% endblock %} |
We're effectively transferring the content from the fos_user_content
block to the correct block: body
.
These 5 lines of code are huge. Refresh the page! Ha! So much better! Not perfect, but every page now lives in our layout. If you want, you can even add a little more markup around the block.
... lines 1 - 2 | |
{% block body %} | |
<div class="container"> | |
<div class="row"> | |
<div class="col-xs-12"> | |
{% block fos_user_content %}{% endblock %} | |
</div> | |
</div> | |
</div> | |
{% endblock %} |
Overriding the base layout is step one. But, each individual page still won't look quite right. On this page, we at least need a "Register" h1
, and I'd like to make that button look better.
So in addition to overriding layout.html.twig
, you really need to override every template from FOSUserBundle that you use - like registration, reset password, login and a few others.
Once again, click the templates link in the web debug toolbar. The template behind this page is register.html.twig
, which we already have open. But notice, it immediately includes register_content.html.twig
. This is a really common pattern in this bundle.
Let me show you: I'll click the views
link to move my tree into FOSUserBundle. In Registration
, we have register.html.twig
and register_content.html.twig
. In Profile
there's the same for edit and show.
In most cases, you'll want to override the _content.html.twig
template. Why? Well, it doesn't really matter: by overriding the _content.html.twig
template, you don't need to worry about extending anything: you can just focus on the content.
Copy the contents of register_content.html.twig
. Then, back in app/Resources/views
, create a Registration
directory. I'm doing that because this template lives in a Registration
directory. Finally, create register_content.html.twig
and paste in the content. Let's add a couple of classes to the button and an h1 that says: "Register Aquanauts!"
{% trans_default_domain 'FOSUserBundle' %} | |
<h1>Register Aquanaut!</h1> | |
{{ form_start(form, {'method': 'post', 'action': path('fos_user_registration_register'), 'attr': {'class': 'fos_user_registration_register'}}) }} | |
{{ form_widget(form) }} | |
<div> | |
<input class="btn btn-primary" type="submit" value="{{ 'registration.submit'|trans }}" /> | |
</div> | |
{{ form_end(form) }} |
Ok, refresh! Love it! In your app, make sure to do this for all of the different pages from the bundle that you're using. And remember, if you don't need a page - like the edit profile page - save yourself some time by not importing its route or overriding its template.
project/templates/bundles/FOSUserBundle/Security/login_content.html.twig
project/templates/bundles/FOSUserBundle/layout.html.twig
I have overriden fos_user_resetting_form with my own... When I did it, I am receiving "Invalid CSRF token" error. I tried to add this to the form: <input type="hidden" id="fos_user_resetting_form__token" name="fos_user_resetting_form[_token]" value="{{ csrf_token('authenticate') }}" /> but it didn't help.
I am customizing the whole form, so I am not using form_widget(form) function call.
This is the whole form:
<form name="fos_user_resetting_form" method="post" action="{{ path('fos_user_resetting_reset', {'token': token}) }}" class="needs-validation" novalidate>
<input type="hidden" id="fos_user_resetting_form__token" name="fos_user_resetting_form[_token]" value="{{ csrf_token('authenticate') }}" />
<div class="form-group">
<label for="fos_user_resetting_form_plainPassword_first" class="required">{{ 'form.password'|trans }}</label>
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-key"></i></div>
<input type="password" class="form-control" id="fos_user_resetting_form_plainPassword_first" name="fos_user_resetting_form[plainPassword][first]" required="required" autocomplete="new-password" />
<div class="invalid-tooltip">Por favor, ingrese la nueva contraseña.</div>
</div>
</div>
<div class="form-group">
<label for="fos_user_resetting_form_plainPassword_second" class="required">{{ 'form.password_confirmation'|trans }}</label>
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-key"></i></div>
<input type="password" class="form-control" id="fos_user_resetting_form_plainPassword_second" name="fos_user_resetting_form[plainPassword][second]" required="required" autocomplete="new-password" />
<div class="invalid-tooltip" id="confirm_password_error">Por favor, ingrese la nueva contraseña.</div>
</div>
</div>
<div>
<button type="submit" id="_submit" name="_submit" class="btn btn-success btn-flat m-b-30 m-t-30">{{ 'resetting.reset.submit'|trans }}</button>
</div>
</form>
Any ideas? Thanks.
Jaime
Hey Jaime,
Hm, probably because you're passing invalid value to csrf_token()... why "authenticate"? It's not an authentication, i.e. login form. If we're talking about ResettingFormType - it should be "resetting", see https://github.com/FriendsO... . I think it should help
Or you can use form_start()/form_end() Twig functions that will render opening and closing form tags and also this hidden csrf token field. But to avoid rendering fields you can call {% do form.plainPassword.setRendered %} before {{ form_end(form) }} call to mark this field as rendered and render it manually with your layout as you do.
Cheers!
Hello... I have finally solved by making the framework to render only that hidden field. I used simply {{ form_widget(form._token) }}. in twig template.
// composer.json
{
"require": {
"php": ">=5.5.9",
"symfony/symfony": "3.3.*", // v3.3.18
"doctrine/orm": "^2.5", // v2.7.0
"doctrine/doctrine-bundle": "^1.6", // 1.10.3
"doctrine/doctrine-cache-bundle": "^1.2", // 1.3.5
"symfony/swiftmailer-bundle": "^2.3", // v2.5.4
"symfony/monolog-bundle": "^2.8", // v2.12.1
"symfony/polyfill-apcu": "^1.0", // v1.3.0
"sensio/distribution-bundle": "^5.0", // v5.0.18
"sensio/framework-extra-bundle": "^3.0.2", // v3.0.25
"incenteev/composer-parameter-handler": "^2.0", // v2.1.2
"knplabs/knp-markdown-bundle": "^1.4", // 1.5.1
"doctrine/doctrine-migrations-bundle": "^1.1", // v1.3.2
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"friendsofsymfony/user-bundle": "^2.0" // v2.0.0
},
"require-dev": {
"sensio/generator-bundle": "^3.0", // v3.1.4
"symfony/phpunit-bridge": "^3.0", // v3.2.7
"nelmio/alice": "^2.1", // v2.3.1
"doctrine/doctrine-fixtures-bundle": "^2.3", // v2.4.1
"symfony/web-server-bundle": "^3.3"
}
}
Hi evryone
Can this tutoriel gonna work with SF4.If yes how i my gona to redirect directories.
Thanks again Ryan & the team for your tutorials :)