Include a controller to get parameter in Twig - symfony

I would like to include a controller into my defaut layout (in app/) to get access to the parameters returned in the array. I don't want to render. I tried to use {{ render_hinclude(controller('L3O1ProjetBundle:Advert:index')) }}
But I'm not sure I understand what it does...
Thanks for your help!

Here is an example from the documentation.
{# app/Resources/views/base.html.twig #}
{# ... #}
<div id="sidebar">
{{ render(controller(
'AcmeArticleBundle:Article:recentArticles',
{ 'max': 3 }
)) }}
</div>
That calls AcmeArticleBundle:Article:recentArticles so first the bundle then the controller and then the function and render the output from that function.
http://symfony.com/doc/current/book/templating.html

It is little bit strange approach to get parameters from the controller without render. But if you really need to get some set of data inside Twig, then the best way will be create a twig extension that will return an array. And if you need same data be returned as the controller makes, better to rebuild the app's architecture: dedicate the controller logic to a service that will return needed values both controller/extension, inject the service to the controller and twig extension and returns data from the service.

Related

A substitute for render(controller())

actually in my project I need to display in the navbar if the user have requests. To do this I use in the twig template a:
{{ render(controller("AppBundle:TeamRequest:numberRequests")) }}
The controller is very simple, just do a doctrine request, and generate a view.
But this part of code is slow... It take 200ms more than if I disable it.
Is there a better way to do this ?
PS: Someone know what is the Symfony\Component\HttpKernel\EventListerner\ProfilerListener ? Because it's this part that take a lot of time in the main and subrequest.
Thanks a lot :-)
Thanks to the answers, the idea is to do a service. In my case, I don't change it, because as you can see in graph, the main part of the time is for the debugbar, finally, it takes few ms to generate it.
All the Timeline (Threshold: 50ms)
Only the subrequest Timeline (Threshold: 1ms)
Try to move this function into a service. Then register this service in twig as a global variable. config.yml:
# Twig Configuration
twig:
globals:
number_requests_service: %your_service_name%
Then in twig you can load it:
{{ number_request_service.renderSomething }}
If you need the user request in the service itself, then give them the request_stack in service configuration.
I had the same problem few day ago, and i solve it with a twig extension you can create it like a service and inject your entityManager to do your request and return a view. With this way Symfony2 isn't load a second time.

Symfony 2: Deserialize object in twig

I'm a newbie and this is my first question so please be nice with me :)
In my Symfony 2 project I want to pass an $user object from my controller to the twig template. This object contains all relevant Information (like username, activepage ...) for rendering the view. My problem is that I would also like to put the result of mysqli database query inside the object. To be able to retrieve it in my twig template, I need two serialize the result object(array?) in the controller before passing. Unfortunately I dont know a way how to deserialize that object in twig( no twig filter available).
My questions:
Is this actually an elegant way or should i rather pass all objects in an array to the template?
Would it work to write a deserialize function inside the user class, which i can call in the twig template?
Will performance be ok?
How do the experienced people do this?
Thx for helping!
Built an array with your data in your controller and render it like this to your template :
return $this->render('yourbundle:example:index.html.twig', array(
'myArray' => $array,
Then in your template you have access to myArray like this :
{% for data in myArray %}
...
{% endfor %}
I made a service such a parameter bag which I can add parameters/values along the process, and render every parameters with twig so I can use them in javascript.
For that I had to use mostly JsonSerializable php interface (PHP 5.4+), and json_decode twig filter.
I think it is a nice way to pass variables to js like this because you can use this service when building your project.

Can I make a user specific method accessible in all twig templates?

I am using Symfony2 with the FOSUserBundle. I have created a method where I ask if the user has done a specific action, e.g. $user->hasVoted().
In my twig templates, I want to be able to ask
{% if user.hasVoted() %}
in every template (because it has an implication on which other partials to include), but I don't want to pass the whole $user object to each template.
Is there any way to make this user method accessible in all templates (or I could also pass the boolean value to all templates) without having to pass this explicitly to each template?
I know about injecting variables into all templates from the Symfony cookbook.
# app/config/config.yml
twig:
# ...
globals:
ga_tracking: UA-xxxxx-x
But the cookbook entry either tells how to inject static values (as in this example above), or how to inject services.
Is there an easy way how to include this one boolean value without having to define a service and inject it like this:
# app/config/config.yml
twig:
# ...
globals:
user_has_voted: "#acme_user.user_has_voted"
The authenticated user is available via app.user everywhere.
{% if app.user.hasVoted() %}
Or the cleaner way, you create a twig extension like is_granted. This enables you, to change the logic behind in future, without changing the templates.
Yes you can, in your bundle boot() method:
// src/Acme/DemoBundle/AcmeDemoBundle.php
public function boot()
{
$hasVoted = $this->container->get('security.context')->getToken()->getUser()->hasVoted();
$this->container->get('twig')->addGlobal('user_has_voted', $hasVoted);
}
Maybe you want to use the "attribute" twig function?
Something like that i guess :
{% if attribute(user, hasVoted) %}
Hope this helps!
(as the doc specifies it here)

Symfony 2 - missing mandatory parameters exception on twig extends

I'm currently getting a very wired twig exception:
If I use the twig {% extends 'some:template' %}, I get the following twig exception:
An exception has been thrown during the rendering of a template ("The "_projectView" route has some missing mandatory parameters ("id").") in "xy:Project:view.html.twig".
But if I remove {% extends 'some:template' %}, the template is displayed correctly - this for my part rules out any problems with routing or the controller, it has to be a problem with the template but I can't figure it out. No variables are used in the parent templates.
Inside the template you're trying to extend you're trying to generate a url from a route '_projectView' but you don't provide all necessary parameters.
Either add a default id to your route ...
route_name:
pattern: /whatever/{id}
defaults: { id: 1 }
... or do something like this in your template:
{{ path('route', { 'id' : entity.id|default('1') }) }}
Quite simply, to display correctly, each twig needs to have all the variables it needs defined. They are either in the URL or passed into the render function. If any of these variables are missing, then Symfony will throw this error.
Given what you've said it seems to me that the twig you are extending has a variable in it that it wants. In all other places you have extended this twig, you have provided this variable already either in the URL or in one of the parent twigs and so it has not complained. In this case you try to use it and that variable is missing. So it complains.
Check to make sure your route passes in the right variable or that your controller passes the right variable into the render function.

Symfony2 - passing values between ESI and main request

I need to pass a value from the main controller in a route to the controller used by an ESI.
So a controller renders a Twig template and in Twig this is called:
{{ render_esi(url('route_name')) }}
The above renders a controller. It's those two controllers I need to pass information between.
I've noticed that using $request->attributes does't work, even though it would if one wasn't an ESI:
//these WON'T pass between master request and ESI
$request->attributes->set('the_value');
$request->attributes->get('the_value');
Sessions aren't ideal as I would need to ensure they were cleared on some occasions.
I really just want the same request to pass some information once. I was hoping that the $request->attributes would be shared as to me it's one request (although I believe Symfony calls it one master request with various sub-requests and I'm guessing $request->attributes are locked to that scope).
Passing it as a query param in the ESI call isn't good either as it can sometimes be an array of info that needs to be passed.
Any ideas?
You can pass arguments to your action like this:
{{ render_esi(controller('YourBundle:Default:news', { 'max': 5 })) }}
or use route parameters like this
{{ render_esi(url('latest_news', { 'max': 5 })) }}
as correctly answered in this question.

Resources