I would like ArrayCollection instead of Doctrine\ORM\PersistentCollection - symfony

I've wrote in a twig view this:
{% for catalog in box.getCatalogs() %}
{% for mod in catalog.getModel() %}
{{ dump(catalog.getModel()) }}
{% endfor %}
{% else %}
nothing
{% endfor %}
I get this in a dump
So how do get an array of collection in a twig view,?

You don't need to worry about the type of Collection object, Both ArrayCollection and PersistentCollection implement the Collection interface and work the same way. The difference is that PersistentCollection contains objects that have been persisted in the DB and might hit the database when you iterate over them.
If you use type-hinting, just hint at Doctrine\Common\Collections\Collection.
If you write
{% for mod in catalog.getModel() %}
{{ dump(mod) }}
{% endfor %}
in your twig template, you should see your objects.

Related

Symfony/ Twig: Filter-filter a collection

Newbie here. Using Symfony 3.4.
I have a Collection of EntityType formtypes I created with the form builder. I'm trying to deposit them on the page selectively. I'd like to loop through them all several times on my template, spitting some of them out according to specific criteria (for instance, the value of a "HiddenType" subtype).
For instance, let's say I had a collection of Movies, some of which have a "Rating" HiddenType. My task is to spit them out selectively in several separate "Rating" sections (i.e. all the R-Rated movies in a single section).
Edit: But! Ratings are user-imputed; dynamically-generated elsewhere. So I can't just make a finite amount of "sections" ahead of time.
My first thought was
{% for rating in ratings %}
<h1>{{rating}}-Rated Movies</h1>
{% for movie in form.movies %}
{% if movie.rating = "R" %}
{{movie}} // put movie formtype/ collection member here somehow...?
{% endif %}
{% endfor %}
{% endfor %}
But I also read that twig has a "filter" filter:
{% for rating in ratings %}
<h1>{{rating}}-Rated Movies</h1>
{% for movie in movies|filter(m=> m.rating == rating) -%}
{{ m }} //put movie formtype/ collection member here somehow...?
{% endfor %}
{% endfor %}
Either way, though, I can't really reconcile the functions I'm familiar with for converting forms to actual html (e.g. form_row() ) with the either of these methods.
Any ideas?
You need to order the movies in your Form by rating. Then in your template do something like this:
{% set rating = null %}
{% for movieForm in form.movies %}
{% set movie = movieForm.vars.value %} <= check if this is the movie entity by dumping it
{% if movie.rating != rating %}
<h1>{{ movie.rating }}</strong>
{% set rating = movie.rating %}
{% endif %}
{{ form_row(movieForm) }}
{% endfor %}

Symfony 5+ nested form collection rendering

{% form_theme form _self %}
{% block collection_entry_row %}
{% set fields = form.attributes.children[0].children %}
{% for key, field in fields %}
{{ form_widget(field) }}
{{ form_widget(fields[key]) }}
{% endfor %}
{% endblock %}
And I get this error:
Neither the property "attributes" nor one of the methods "attributes()", "getattributes()"/"isattributes()"/"hasattributes()" or "__call()" exist and have public access in class "Symfony\Component\Form\FormView".
But this
{% set fields = form.attributes.children[0] %}
{% for key, field in fields %}
{{ dump(field) }}
{% endfor %}
Produces this:
Symfony\Component\Form\FormView {#2150 ▼
+vars: array:33 [▶]
+parent: Symfony\Component\Form\FormView {#2203 ▶}
+children: []
-rendered: false
-methodRendered: false
}
And yet inside the form_start() I can do the following and render one field at a time:
{% set tempInput = form.children['attributes'].children[0].children['attributes'].children[0].children['pin'] %}
{{ form_widget(tempInput) }}
Thoughts?
just had the same questions as you about this subject, and since i didn't understands the way to use the "{% block collection_row %}" i've found this following workaround.
I find out that the problem i had was coming from the 2 last item of the form.children: "submit" and "_token".
Because, of course, they will not have the variable name you are searching in the other "real" forms childs.
So i just added a check to the length of the children array to exclude this "submit" and "_token" items.
(The test might certainly be different for your case).
{% for child in form.children %}
{% if not child.children | length != 4 %} // my array has 4 items, submit and _token have none
{{ form_widget(child.children.variableName) }}
{% endif %}
{% endfor %}
As you can see you can access your collection variable between the if like this:
{{ form_widget(child.children.variableName) }}
Peace.

Twig - loop default value

I am trying to print array from the cotroller into the twig temlate. I want to print "-" whenever array is NULL. My problem is that in for-loop case it writes nothing, however single row working fine. Is there some simple way how to do it correctly?
this is not working as i expected
{% for key in keywords|default('-') %}
{{ key~', '}}
{% endfor %}
this is working
{{ key |default('-')}}
You can use an {% else %} construct on a for loop to do something else if the array is null:
{% for key in keywords %}
{{ key~', '}}
{% else %}
-
{% endfor %}
See the documentation here.

Join property values of a list of objects in twig

Is it possible to join the values of properties of a list of objects for displaying it?
Something like:
{{ users|join(', ', username) }}
Where users are objects, having a getUsername() method.
I suppose join doesn't take an additional argument, but is there a workaround to achieve something similar? I can not use the __toString() function, as it represents something else...
or have the same result with just one forloop
{% for user in users %}
{{ user.username }}{% if not loop.last %}, {% endif %}
{% endfor %}
You can use map() filter… and fit everything in one line:
{{ users|map(u => u.username)|join(', ') }}
You could use..
{% set usernames = [] %}
{% for user in users %}
{% set usernames = usernames|merge([user.username]) %}
{% endfor %}
{{ usernames|join(', ') }}
Not the prettiest though.
You could always make a custom twig filter to do it.
A shorter version of digital-message's idea:
{% for user in users %}
{{ user.username ~ (not loop.last ? ', ') }}
{% endfor %}

How do you check if an object exists in the Twig templating engine in Symfony2?

I have a multidimensional array where some objects exist and others don't. I keep getting a
Method "code" for object "stdClass" does not exist in...?
The code I am using in my template is:
{% for item in items %}
<p>{% if item.product.code %}{{ item.product.code }}{% endif %}</p>
{% endfor %}
Some products do not have this code and unfortunately this data structure is provided via a feed, so I cannot change it.
When I looked at the Twig documentation I interpreted that if an object or method was not there it would just return null?
Quickly did a lookup, hope this is works for you :p
defined
defined checks if a variable is defined in the current context. This is very useful if you use the strict_variables option:
{# defined works with variable names #}
{% if foo is defined %}
...
{% endif %}
{# and attributes on variables names #}
{% if foo.bar is defined %}
...
{% endif %}

Resources