I've not been able to find anything useful about this in the Twig or Symfony2 documentation, so thought I would ask here.
Does anybody know if it's possible to include a Twig template in Symfony2 relative to the current bundle, without specifying the name? Something along these lines:
{% include .:Foo:bar.html.twig %}
I'm just a bit fed up of having to enter the long, ugly bundle name when they're all in the same bundle. Also means if the bundle name ever changed for whatever reason, I'd have to find & replace every single include.
Back in the days when I was using bundles, I came up with a quick solution that you could base upon:
{% set bundle = app.request.get('_template').get('bundle') %}
{% set controller = app.request.get('_template').get('controller') %}
{% include bundle ~ ':' ~ controller ~ ':foo.html.twig' %}
Related
I am wondering what is best perfomance-wise, using
{% include "_inc/template" %}
or
{% include "_inc/template" with {'foo': bar %}
assuming foo is the only variable used in _inc/template and it's also available in global context.
Will there be significant difference in performance between two approaches, if the include is placed within for having ~50 loops?
I don't have direct answer to your question, but you can use the profiler in dev toolbar to see the timeline of the calls.
Maybe try and tell us...
Which is the version of symfony you use?
I know that in symfony > 2.7 the timeline Graph exist.
Ps : Maybe try it with this too:
{% include 'template.html' with {'foo': 'bar'} only %}
I'm pretty new to Symfony development and i just tried to use the FOSUserBundle. I followed the guide Getting Started With FOSUserBundle on the official Symfony website.
Afterwards i wanted to test the functionality of the installation and visited the link www.linktomytestproject.dev/login which worked flawlessly. But when i tried to visit www.linktomytestproject.dev/register to test the registration functionality, i got the following errormessage:
Unable to find template "register_content.html.twig" (looked into: /home/vagrant/mytestproject/app/Resources/views, /home/vagrant/mytestproject/vendor/symfony/symfony/src/Symfony/Bridge/Twig/Resources/views/Form) in #FOSUser/Registration/register.html.twig at line 4.
500 Internal Server Error - Twig_Error_Loader
I checked the file register.html.twig, which contains the following code:
{% extends "#FOSUser/layout.html.twig" %}
{% block fos_user_content %}
{% include "register_content.html.twig" %}
{% endblock fos_user_content %}
When I change the third line into:
{% include "FOSUserBundle:Registration:register_content.html.twig" %}
The file is found correctly and i can use the registration functionality as intended.
But the change i made is inside the vendor folder, which obviously isn't affected by any means of version control. So i guess there has to be a place somewhere in the configuration files, where this file/foldermapping is affected.
I would really appreciate it, if someone could help me out with this question, even though this is probably a really basic problem.
First override the FOSUserBundle http://symfony.com/doc/current/bundles/FOSUserBundle/overriding_controllers.html
After that, you can create view folders like in vendor and you can use views like that;
{% include "YourBundle:Registration:register_content.html.twig" %}
It's a bug a issue is open on github
Is a bundle issue, in my project I change on the file
\vendor\friendsofsymfony\user-bundle\Resources\views\Registration\register.html.twig
this
{% include "register_content.html.twig" %}
for this
{% include "#FOSUser/Registration/register_content.html.twig" %}
I would like to configure multiple URLs to one Action in Controller (internationalization purposes).
According to this answer it was surely possible in symfony2 to:
Make double annotation route.
Use 3rd party Bundle (for example "BeSimple's").
But I'm using Symfony 3.0.3 which prohibits me from doing so until I change the route's name (example):
/**
* #Route("/welcome", name="welcome", defaults={"_locale" = "en"})
* #Route("/bienvenue", name="welcomeFR", defaults={"_locale" = "fr"})
* #Route("/willkommen", name="welcomeDE", defaults={"_locale" = "de"})
*/
But adding additional "FR/DE" chars to routes change their presence and ruins my URL generating logic in template, I'm forced to make on all links:
{# homepage example #}
{% if _locale = 'en' %}
{{ path('welcome') }} {# Routes from set only for "en" #}
{% elseif _locale = 'fr' %}
{{ path('welcomeFR') }} {# "fr" only links #}
{% endif %} {# and so on #}
Anyone found the proper solution for this problem?
AFAIK, this is the preferred way to point multiple routes to an unique controller action. So, your current problem is to regenerate the current path, depending on which route is being used
Maybe you don't have to modify your logic if you use {{ app.request.get('_route') }} to get the name of your current routing. This way, you could use:
{{ path(app.request.get('_route')) }}
UPDATE:
What about create an action per route and forwarding them to the main language action? Maybe it is not the best practice, but could work fine
/**
* #Route("/welcome", name="welcome", defaults={"_locale" = "en"})
*/
public function welcomeAction()
{
/* code here */
}
/**
* #Route("/bienvenue", name="welcomeFR", defaults={"_locale" = "fr"})
*/
public function welcomeFrAction()
{
$response = $this->forward('AppBundle:ControllerName:welcome');
}
/*
* #Route("/willkommen", name="welcomeDE", defaults={"_locale" = "de"})
*/
public function welcomeDeAction()
{
$response = $this->forward('AppBundle:ControllerName:welcome');
}
After wasting 10 hours on finding solution on Symfony3 I've made those assumptions:
None of the route trick with exactly same "name" wouldn't work,
Any kind like double annotation, double "routing.yml" importing, host based matching gives the same effect - only one route is matched, usually the last one. Would be ("/willkommen", name="welcomeDE") in my example.
Both of the i18n bundles does not work on Symfony3 through the versioning constraints,
Composer wouldn't even let us install the bundle.
Locale Listener and Loader (Routing Component) is dying on caching.
My solution to match the "_locale" and pass it to the LocaleLoader in order to load "routing_en.yml/routing_fr.yml" etc. files respectively is cached on the first match by the Symfony and after that, changing the "_locale" does not affect route's mapping.
In conclusion
Symfony3 seems not supporting route "example" with more than one "url" at all. Through the constraints and caching.
After the disappointment I'm considering going back to Symfony 2.8, have no idea what was pointing Symony's masters to block "double annotation" solution and what is their current idea on links internationalization.
Hope someday it will be possible to achieve with S3, as link i18n is quite common SEO practice.
EDIT: Confirmed, working like a charm on 2.8.5 with BeSimple's i18n.
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 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.
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:
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 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.
Is there a way with Symfony2 and Twig to always make files available which just contain blocks.
For example, if I wanted to make a block named 'cookie' always available in any template in my system, without having to always include or extend it in the template I'm using.
Any ideas?
Clarification
Say I have a generic block which can do something, like:
{% block myBlock %}
ABC Examples
{% endblock %}
I have a class which knows it wants to be rendered with this block. My template itself doesn't necessarily know this though.
{{ block(myObj.blockName) }}
I would then like to have it so my controller/services/etc. could register the file which contains that block, without my template actually needing to know about it directly (so I could have multiple files like that, each working with some common interface).
Similar to registering custom Twig functions with a TwigExtension. My template doesn't need to explicitly know it's there, it just has to be available at run-time.
Does that make sense?
To clarify a bit further, I'm essentially looking to do something just like how there are default Twig blocks for rendering Forms in Symfony2. I don't have to include the default form file every time, just when I want to change something.
I went digging around in the Symfony source code to try and find my answer. It looks like there isn't some fancy, neat way to embed it from a configuration file or controller directly, which is a bit disappointing, but not a huge deal.
So, to solve my situation, I'll be using the "use" keyword to include my block file in my base template, so it will then be available to everything else.
{# widget_blocks.html.twig #}
{# Widgets #}
{% block my_widget %}
ABC Cookies
{% endblock %}
{# base.html.twig #}
{% use widget_blocks.html.twig %}
{{ block(my_widget.block) }}
Not exactly what I wanted, but sufficiently close.
{% render 'MyMainBundle:Default:credits' with {'arg1': $myObj } %}
Thats what I say. What's the difference between the line above or
{{ block(myObj.blockName) }}
You can register a custom filter but as far as I know it returns only string value. http://twig.sensiolabs.org/doc/advanced.html#id2