How to run an object's method in twig without rendering what it returns [duplicate] - twig

I have seen the twig documentation about do tag, but I don't understand its use/useful.
The docs says the follow:
The do tag works exactly like the regular variable expression ({{ ...
}}) just that it doesn't print anything:
and show an example:
{% do 1 + 2 %}
What to solve exactly this tag ?

Good question! I found a link on GitHub to when this was proposed which might add some further info:
Sometimes you want to do things, or call some stuff, and ignore the output. For example if you use a |shift filter to remove some data from an array, doing {{ arr|shift }} will output the removed item, which is not always desirable.
Of course it's possible to do {% set null = arr|shift %}, which won't
output anything, but it also looks weird.
The example in the docs is poor as it explains nothing at all, as you pointed out.

Related

Calling method in Twig, how to avoid the return showing as output

I am calling a method in a pre-existing object from inside a Twig template, after properly authorizing it in policy:
{{ thisEmail.AddCC('me#example.com') }}
My problem is that the object method, which I use to produce a side-effect, not to return any text, returns true, and that leaves a visible "1" in my template output.
How to remove this output? I have this one working:
{{ thisEmail.AddCC('me#example.com')|trim('1') }}
But I feel it's not entirely elegant, and it can only remove that specific result. I would prefer to write something like |nul or |drop and have the filter drop everything, regardless of how much or what kind of stuff it receives as input.
I know how to do it by writing my own Twig extension filters, but my question here is: is there a nice way of achieving this with the core Twig language, un-extended?
If you want a twig statement not to output anything you can use the do tag, e.g.
{% do thisEmail.AddCC('me#example.com') %}
source

PhpStorm code completing for Twig templates

When accessing a method via a Twig template the method name is always shortened and the prefix is removed.
For example: {{ object.getName }} gets completed to {{ object.name }} whenever I try to use the full method name, code completion will show nothing but if the full method name is finally entered manually it resolves the method just fine and I can jump to it.
I really really dislike this but could not find a way to disable the behavior. Is it even possible or someone can give me a hint what to do about it?

Can't iterate the "filter" filter multiple times

I am trying to assign the result of the "filter" filter (available since Twig 2.10) to a variable so that I can use it multiple times:
{% set filtered = collection|filter(element => element.ok) %}
But unfortunately, if I try to iterate over it multiple times (using the "length" filter counts as such), I get the error
Cannot traverse an already closed generator
after the first one. The error is pretty clear that "filter" actually returns an Generator (which I believe can't be iterated multiple times) and not an array or collection.
The problem is that it makes it impossible to write the following code, for example:
{% if filtered|length > 0 %}
<ul>
{% for element in filtered %}
<li>{{ element }}</li>
{% endfor %}
</ul>
{% endif %}
This code would trigger the error mentioned above on the for loop.
Instead of using a variable I could refilter the original collection, but that doesn't seem optimal if it contains a lot of elements.
I also thought about writing my own filter, wrapping the original one, but I'd live better if I didn't have to.
Is there anything better to do? Should this be considered a bug in Twig (in which case I'll open an issue in their repo)?
Note that https://github.com/dpolac/twig-lambda didn't exhibit this strange behavior but is not compatible with Twig 2.10.
Thanks
That was indeed a bug and it is now fixed

page.collection() is empty despite having child pages

I'm using Masonry theme and trying to show all posts in a collection. Masonry does this normally and I had it working previously, but now page.collection is empty despite having pages. I've made sure that the children are routable and visible. I even reinstalled the theme, to no avail. Any ideas? At this point I haven't actually modified any code that would affect that page logic relating to the collections.
At the top of the file is:
{% set collection = page.collection() %}
I used
{{dump(collection)}}
But nothing shows up. What gives?
I changed page.collection to page.children instead. It accomplishes the same thing without having to add extra header content on my page. Thanks to HungTran for pointing out the correct way though.
If collection() is indeed a method, then you would use this in Twig instead:
{% set collection = page.collection %}
Can you try that. I'm not certain it will work, but let us know the result.

Passing string variables through include in twig and slim framework

I am using Slim Framework and Twig.
I want to apply the DRY by using partials. I have a form that is reused in several views with different variables such as titles and route (url) names.
I am struggling on how to make it work on url names.
For example, there is this link using the ´urlFor´ helper with parameter as follows inside a view:
The link
So that is the link I want to pass to the partial template since, it is different in each view, I want to use the partial form. I have tried several approaches but it does not work. I don't know how to pass this string containing ' inside.
For example, I have tried this partial call inside the parent view like this:
{% include 'partials/partial.php' with {'theUrl': "urlFor('route.name', {parameter: value})"} %}
And inside the partial like this:
Show more
It does not work because in the browser's url I see the following:
http://myproject.dev/pages/urlFor('route.name',%20%7Bparameter:%201%7D)
It looks like it is not being escaped properly. Any ideas how to fix this when passing route names with urlFor()?
Without the greatest possibility for testing i think i found the problem. You are simply adding the function inside a string and that does not give the parser an oportunity to resolve the method, because it's basicly just a string.
{% include 'partials/partial.php' with {'theUrl': "urlFor('route.name',{parameter: value})"} %}
Should be
{% include 'partials/partial.php' with {'theUrl': urlFor('route.name',{parameter: value})} %}

Resources