Symfony 2: Deserialize object in twig - symfony

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.

Related

In Symfony template (twig), how to fetch an object by its id?

I have an ID of object in Symfony twig template. How can I transform this ID in the corresponding object? In EZ Publish there was a special FETCH function to do that, but in Symfony it does not exist. Thanks for any advice.
Twig is for the view only, your data must be returned by the controller, where you can find object by it's ID
I don't know if that is what you need, but in twig you can do
{{ render(controller('YourBundle:Controller:Action', {'objectId' : objectId})) }}
to render some other object/content.

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)

how to do a preg_replace in twig

I currently am trying to make a variable using the current url for the view. To get the url, I am using {% set uri = app.request.uri %} (uri being my variable which is the current url for that particular view). The thing is, I am only interested in what makes the url unique (the end of it - a unique object from an array - happens to be a uri), and not the beginning (path to my application). I was thinking I could use a preg_replace to do so, but TWIG doesn't have this function. Just wondering if someone would know how to accomplish what I am trying to do?
I'm new to Symfony (and fairly new to PHP), so my explanations may not be clear (sorry).
Ex.
{% set uri = app.request.uri %}
output: http://website.com/http://item.org/1
I want to modify the uri variable to ONLY have http://item.org/1 (and not the path to my website).
I'm thinking creating a Twig Extension with the preg_replace will allow me to do this ..but not sure if it's the best way to go (inexperienced).
Overall goal:
The unique value for "uri" in the view is appended to the websites path by another view from an array of objects ($results) with attributes, one being "uri". My ultimate goal is to only display all associated attributes (or row) for an object in my $results array. I was thinking I could do this by first creating a key (my uri variable) in a foreach, and returning the row in the array which matches this key. This is why I am trying to create a variable with the url so that I can use it as a key for my foreach loop to iterate over $results. I am NOT using a database or Doctrine.
Thank you ahead of time for the help!
The best way is to move the logic from template to the controller.
If you need preg_replace in twig you must create custom extension.
Someone seems to have created a Twig Extension for preg_replace, see https://github.com/victor-in/Craft-TwigPCRE
You can do it like that. It's a bit ugly but it works.
uri|split('base_path')|join('')

Is there a way to get twig to consider a method of a passed object as safe?

I am having issues with twig escaping output on method calls to an object passed into my twig template. I know I can get around this with the |raw filter, but was hoping there might be a way I could simply specify in my object that certain methods are safe and therefore remove the need for the raw filter.
Method calls of objects itself cannot be made html safe because normal objects/entities are not (and should not be) aware of the template engine.
However, a twig filter or function if aware of the template engine and can be marked html safe in its definition.
So what you need to do is to implement a html safe twig filter to pass the object to and call the method of your object inside the filter function.
I guess your templates looks like this:
<p>{{myObj.getHtmlRepresentation()|raw}}</p>
Now you need to implement a twig filter and change the template to the following:
<p>{{myObj|html_representation}}</p>
And the twig extension should look like this:
class MyTwigExtension {
public function getFilters(){
return array(
// the magic is the is_safe=>html option
'html_representation' => new \Twig_Filter_Method($this,'htmlRepresentation',array('is_safe'=>array('html'))),
}
public function htmlRepresentation($obj){
return $obj->getHtmlRepresentation();
}
}
One design consideration: If your object is an entity of a business object of some kind, it sould not create html but you should move the html creation to a template or the twig filter..

How to loop through the variables of an entity in twig?

I'm using symfony2 and have accessed an entity using a doctrine query, which I then pass to my twig template. This entity has variables that I would like to loop through without having to explicitly name each one. Is there a way I can do this with twig or should I try a different design?
Twig documentation says:
A sequence can be either an array or an object implementing the
Traversable interface.
So it should work as long as you implement one of the Traversable interfaces (IteratorAggregate or Iterator).

Resources