Twig nested loop - php

I'm a new Twig user, and I'm with troubles to fill a grid...
I have a entity called "menu", and want to access just some atributes, so I created an array like this:
$itens = array(
array('name' => 'id', 'label' => 'Id'),
array('name' => 'parent', 'label' => 'Pai'),
array('name' => 'name', 'label' => 'Nome'),
array('name' => 'route', 'label' => 'Rota'),
array('name' => 'position', 'label' => 'Posição'),
);
So I'm trying to do a nested loop to access this informations... but I don't know how do it. I tryed like this, but obviously it's wrong.
<tbody>
{% for menu in menus %}
<tr>
{% for item in itens %}
<td> {{ menu.[item.name] }} </td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
How can I do it???
in PHP code, it's looks like it:
foreach $menus as $menu {
echo "<tr>";
foreach $itens as $item
echo "<td>".$menu[$item["name"]]."</td>";
echo "</tr>";
}

Try this,
<tbody>
{% for menu in menus %}
<tr>
{% for item in items %}
<td> {{ menu[item.name] }} </td>
{% endfor %}
</tr>
{% endfor %}
</tbody>

Keep in mind that twig is very similar to PHP. Your template should look like this:
<tbody>
{% for menu in menus %}
<tr>
{% for item in menu %}
<td> {{ item.name }} </td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
Note that this will be translate to something like this in PHP:
foreach ($menus as $menu) {
foreach ($menu as $item) {
// ...
}
}
More on twig loops can be found in the twig documentation.

Related

dynamically render table in twig

I am familiar with how to render table in twig but have this data in array that i can not figure out how to render it in a twig table.
$data = [
'product' => $product,
'qty' => $qty,
'price' => $price,
'total' => $total,
];
the above are in array so if i do something like
{% for product in products %}
{{ products }}
{% endfor %}
it displays all this records in products.
Now in twig table trying to render it means i have to do multiple for loops which does not work as it is supposed to. For instance
{% for product in product %}
<tr>
<td>{{ product }}</td>
</tr>
{% endfor %}
{% for price in price %}
<tr>
<td >{{ price }}</td>
</tr>
{% endfor %}
The above just displays it on one row
Really confused how to output something like this in a twig table
Product is an element inside the array so you should use something like data.product instead of just product
Something like this should do the trick:
<table>
{% for dat in data %}
<tr>
<td>{{ dat.product }}</td>
<td>{{ dat.qty }}</td>
<td>{{ dat.price }}</td>
<td>{{ dat.total }}</td>
</tr>
{% endfor %}
</table>

Symfony 4 user search by email issues

I am trying to implement a search for user by email function into page admin's dashboard. Currently, I have hardcoded a value into $email variable just to test whether the search works. It does find the right user, but does not display anything in the twig.
Executing {{ dump() }} outputs: array:2 [▼ 0 => User {#4745 ▼ -id: 5 -
username: "test_user" -plainPassword: null -password:
"$2y$13$rGYteIrzifg9Dty.O5knOOCHQnzOtF.nZux8h1jc4sNbap5V7Xn0." -email:
"tester#test.com" } "app" => AppVariable {#2617 ▶} ]
the function I use in AdminController.php:
/**
* #Route("/admin/result", name="user_search")
* Method({"POST"})
*/
public function user_search(Request $request)
{
$email = 'tester#test.com';
$result = $this->getDoctrine()
->getRepository(User::class)
->findOneBy(['email' => $email]);
if ($result) {
return $this->render('admin/result.html.twig', $result);
}else{
return $this->render('admin/result.html.twig', [
'error' => 'No user found with this email '.$email]);
}}
result.html.twig:
{% extends 'base.html.twig' %}
{% block body %}
{% if error %}
<span class="error">{{ error }}</span>
{% endif %}
{% if result %}
<table>
<tr>
<th>Username</th><th>Email</th>
</tr>
{% for item in result %}
<tr>
<td>{{ item.getUsername }}</td><td>{{ item.getEmail }}
</td>
</tr>
{% endfor %}
</table>
{% endif %}
{{ dump() }}
{% endblock %}
In twig you assume that the result is an array. For this, uses findBy instead of findOneBy. findBy returns an array of objects with the desired search. The findOneBy return only an object with the desired search or null if results are not found.
Example:
// look for a single User by email
$result = $this->getDoctrine()
->getRepository(User::class)
->findOneBy(['email' => $email]);
// look for multiple User objects matching the email
$result = $this->getDoctrine()
->getRepository(User::class)
->findBy(['email' => $email]);
This was finally solved by these steps:
There was a typo in the hardcoded $email variable.
Changed return $this->render('admin/result.html.twig', 'result'->$result); instead of return $this->render('admin/result.html.twig', $result);
Changed <td>{{ item.username }}</td><td>{{ item.email }}</td> instead of <td>{{ result.getUsername }}</td><td>{{ result.getEmail }}</td>
Check $user with instance
if ($result instanceof User)
.......................................................................
I suggest you use defined in twig
{% if result is defined %}
{% extends 'base.html.twig' %}
{% block body %}
{% if error is defined %}
<span class="error">{{ error }}</span>
{% else %}
<table>
<tr>
<th>Username</th><th>Email</th>
</tr>
{% for item in result %}
<tr>
<td>{{ result.getUsername }}</td><td>{{ result.getEmail }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
{% endblock %}

Two dimensional array in Twig

I have satellite images stored in a mysql database. The table has attributes latitude,longitude. I want to send them to the twig and display as a map, my php controller looks like this.
public function highlightAction()
{
$highlighted=$this->getDoctrine()
->getRepository('AppBundle:satelliteImage')
->findAll();
$images = array();
foreach ($highlighted as $key => $high) {
$images[$key] = base64_encode(stream_get_contents($high->getImage()));
}
return $this->render('satelliteImages/highlighted.html.twig',array(
'highlighted' => $highlighted,
'images' => $images
));
}
My twig code is this:
<tbody>
{% for key,high in highlighted %}
<tr>
<img alt="Embedded Image" src="data:image/png;base64,{{ images[key] }}" />
</tr>
{% endfor %}
</tbody>
I am displaying the images as a vertical array. Any suggestions, I might need to display them as a map.
A two dimensional array in twig?
You can use something like this:
<table>
<tbody>
{% for key in 0..2 %}
<tr>
{% for key in 0..3 %}
<td>
<img alt="Embedded Image" src="data:image/png;base64,
{{ images[loop.parent.key*4 + key] }}" />
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
Read the Twig for documentation.

Symfony2 Table with 3 entity in Twig

First of all, sorry by advance for my english which is not perfect.
I have a problem for days by reporting 3 doctrine entity in a Twig Table template.
It's a table for manage stocks at work. I have different materials which have each different sizes. Each couple (1 material + 1 size) got a number as amound to order.
So I first created 3 entity :
Stock (represent materials) ManyToMany Dimension (represent sizes)
Besoin (needs) got a ManyToOne relation with both Stock and Dimension.
Then, I created few Stocks, Dimensions and needs with my forms to get a test database.
The goal is now to create a double entry table with the dimensions list, Stocks list and in each cell the needed number.
It's in this step that I have bugs.
For now I can give you my code and hope someone can help me by giving me a tips.
Controller :
public function commandeAction()
{
$em = $this->getDoctrine()->getManager();
$materiauxlist = $em->getRepository('TGComptaBundle:Stock')->findAll();
$dimensionslist = $em->getRepository('TGComptaBundle:Dimension')->findAll();
$tab1 = array_merge($materiauxlist, $dimensionslist);
$besoins = array();
foreach ($materiauxlist as $stock) {
foreach ($dimensionslist as $dimension) {
$besoin = $em->getRepository('TGComptaBundle:Besoin')->findBesoins($stock, $dimension);
}
}
return $this->render('TGProdBundle:Projet:stocks.html.twig', array(
'materiauxlist' => $materiauxlist,
'dimensionslist' => $dimensionslist,
'besoin' => $besoin));
}
View :
{% block tgprod_body %}
<div class="well">
<table class="table table-hover table-bordered">
<thead>
<tr>
<th>#</th>
{% for dimension in dimensionslist %}
<th>{{ dimension.name }}</th>
{% endfor %}
</tr>
</thead>
{% for stock in materiauxlist %}
<tr>
<td>{{ stock.name }}</td>
{% for dimension in dimensionslist %}
{% if besoin %}
<td>{{ besoin.nombre }}</td>
{% else %}
<td>X</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</table>
</div>
{% endblock %}
Repository :
public function findBesoins($stock, $dimension)
{
$qb = $this->createQueryBuilder('b');
$qb
->where('b.stock = :stock')
->andwhere('b.dimension = :dimension')
->setParameter('stock', $stock)
->setParameter('dimension', $dimension);
$qb
->getQuery()
->getResult();
}
My actual problem is : I have X in all cells
Before I asked your help I tried :
foreach ($materiauxlist as $stock) {
foreach ($dimensionslist as $dimension) {
$besoin = $em->getRepository('TGComptaBundle:Besoin')->findBesoins($stock, $dimension);
$besoins[] = $besoin;
}
}
and :
<table class="table table-hover table-bordered">
<thead>
<tr>
<th>#</th>
{% for dimension in dimensionslist %}
<th>{{ dimension.name }}</th>
{% endfor %}
</tr>
</thead>
{% for stock in materiauxlist %}
<tr>
<td>{{ stock.name }}</td>
{% for dimension in dimensionslist %}
{% for besoin in besoins %}
{% if besoin %}
<td>{{ besoin.nombre }}</td>
{% else %}
<td>X</td>
{% endif %}
{% endfor %}
{% endfor %}
</tr>
{% endfor %}
</table>
But it was wrong result (I had like 10000 X on each row)
I thinked it's the "{% for besoin in besoins %}" which is wrong, it should be something like "{% for besoin.dimension.stock in besoins %}" but I can't write this in twig.
and I tried something like this to :
$table = array('stock' => $stock, 'dimension' => $dimension, 'besoin' => $besoin);
$besoins[] = $table;
when I do a { dump() } in Twig I have array with number of stock x number of dimension and all with a null besoin so it seems strange ... and finally I didn't find how to render this array in my table so I let this solution away :/

Symfony 2 - best approach for summing results of values in related entities

My code is aimed at getting items from database. Those item may have either debit values or credit values. In template I present all of the values but would like also to provide information about sum of debit and account values connected with the account ($account_id)
What would be your best practice how to do this?
Should I simply run another two SQL queries:
first to SUM(value) where accountdebet = '.$account_id
secound to SUM(value) where accountcredit = '.$account_id?
Will it be the right approach?
Controller:
// Get items for acccount and paginate
$rp_items = $this->getDoctrine()->getManager()->getRepository('AppBundle:Items');
$query = $rp_items->createQueryBuilder('p')
->where('p.accountdebet = '.$account_id)
->orWhere('p.accountcredit = '.$account_id)
->getQuery();
$rp_paginator = $this->get('knp_paginator');
$db_pagination = $rp_paginator->paginate($query,$this->get('request')->query->getInt('page', 1),10);
// Render TPL
return $this->render('AppBundle:Accounts:items.html.twig', array('pagination' => $db_pagination, 'account' => $account));
In twig:
{% extends '::base.html.twig' %}
{% block body %}
<B>Item list for account {{ account.id }} </B><BR>
Account id: {{ account.id }}<BR>
Account marker: {{ account.marker }}<BR>
Account name: {{ account.name }}<BR>
<table class="table table-striped">
<tr>
{# sorting of properties based on query components #}
<th>{{ knp_pagination_sortable(pagination, 'Id', 'a.id') }}</th>
<th{% if pagination.isSorted('a.itemdate') %} class="sorted"{% endif %}>{{ knp_pagination_sortable(pagination, 'Date', 'a.itemdate') }}</th>
<th>Document</th>
<th>{{ knp_pagination_sortable(pagination, 'Marker', 'a.marker') }}</th>
<th>Debit</th>
<th>Credit</th>
</tr>
{# table body #}
{% for item in pagination %}
<tr>
<td>{{ item.id }}</td>
<TD>{{ item.itemdate|date('Y-m-d')}}</TD>
<td>{{ item.documentid.marker }}</td>
<td>{{ item.marker }}</td>
<TD>{% if item.accountdebet.id == account.id %}
{{ item.itemvalue}}
{% endif %}
</TD>
<TD>{% if item.accountcredit.id == account.id %}
{{ item.itemvalue}}
{% endif %}</TD>
</tr>
{% endfor %}
</table>
{# display navigation #}
<div class="pagination">
{{ knp_pagination_render(pagination) }}
</div>
{% endblock %}
You can solve it in many ways but i like to make an parent entity eg ItemsCollection that holds an arrayCollection of Items. Then i give the new entity some extra functionality e.g.
public function countItemValues()
{
$total = 0;
foreach($this->items as $item)
{
$total += $item->getValue();
}
return $total;
}

Categories