Twig representation of array - php

How can I represent array data given in the following format:
array(3) {
[0]=> array(4) {["cohort"]=5 ["total"]=5 ["week"]=1 ["active"]=2 }
[1]=> array(4) {["cohort"]=5 ["total"]=5 ["week"]=2 ["active"]=1 }
[2]=> array(4) {["cohort"]=6 ["total"]=3 ["week"]=1 ["active"]=1 }
}
To be shown in twig like this:
cohort| total| 1 (week) | 2 (week)
------------------------------------
5 | 5 | 2 | 1
6 | 3 | 1 | -
My problem, is that I don't know how to loop through the array, so that I only get row numbers equal to unique cohort number (only 5 and 6, not 5,5,6), get 'week' number as column name and 'active' value to be shown in relevant 'week' column and relevant cohort row
I tried to do this:
<table>
<tr><td>Cohort</td><td>Registered users</td>
{% for week in logged_users %}
{% if week.week_number not in weekArray %}
<td>{{week.week_number}}</td>
{% set weekArray = weekArray|merge([week.week_number]) %}
{% endif %}
{% endfor %}
</tr>
{% for data in logged_users %}
<tr>
{% if data.cohort not in cohortArray %}
<td>{{data.cohort}}</td>
<td>{{ data.total_users }}</td>
{% for active in logged_users %}
<td>{{ active.active_users }}</td>
{% endfor %}
{% set cohortArray = cohortArray|merge([data.cohort]) %}
{% endif %}
</tr>
{% endfor %}
</table>
but in the result I get this:

<table>
<thead>
<tr><th>cohort</th><th>total</th><th>1 - week</th><th>2 - week</th></tr>
</thead>
<tbody>
{% for i,a in data %}
<tr>
<td>{{ a.cohort }}</td><td>{{ a.total }}</td><td>{{ (a.week==1 ? a.active : '-') }}</td><td>{{ (a.week==2 ? a.active : '-') }</td>
</tr>
{% endfor %}
</tbody>
</table>

Related

Twig dividing data into tables

I am working on a webapplication but ive ran into a hiccup, I have gathered data from my database and displayed the records into a datatable, my problem is that I can not just have one table the client wants me to divide the table into multiple based on what interger is in a column(omloopNummer).
The best ive gotten so far is with the following code it wil split the table up into lets say 4 tables if the interger in the database wil go 1,2,3,4 but it wil only show 1 record in each table while it should be more.
If there is any other simple solution to this instead of using twig I would be happy to try it.
<div id="index" class="table-responsive">
{% set i = 1 %}
{% for duel in duels %}
{% if duel.omloopNummer == i %}
{% set i = i + 1 %}
<table id="" class="table display-" style="width: 90%; margin-top: 30px">
<thead>
<tr>
<th>Omloop</th>
<th>Team 1</th>
<th>vs</th>
<th>Team 2</th>
<th>Acties</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ duel.omloopNummer }}</td>
<td>{{ duel.team1 }}</td>
<td>vs</td>
<td>{{ duel.team2 }}</td>
<td>{{ include('duel/_delete_form.html.twig') }}</td>
</tr>
</tbody>
</table>
{% endif %}
{% endfor %}
You could use PHP to group Duels by omloopNummer in the controller before passing to twig.
$duels = $duelRepository->findAll();
$sorted = [];
foreach($duels as $duel){
$sorted[$duel->getOmloopNummer()][] = $duel;
}
return $this->render('template.html.twig', [
'duel_groups' => $sorted,
]);
Then in twig, loop through the sorted array building a table for each non-empty group and inside each tbody loop through the group.
{% for group in duel_groups %}
...
{% if group is not empty %}
<table>
...
<tbody>
{% for duel in group %}
<tr>...</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
...
{% endfor %}

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 %}

Convert Key Value to matrix in twig

I using twig to render data, to html. Data I got from server is a key-value. for example :
| Key | Value |
|-----|-------|
| A | 1 |
| A | 2 |
| B | |
| C | 10 |
I need to render this data to table like this :
| A | B | C |
|---|---|----|
| 1 | 0 | 10 |
| 2 | 0 | 0 |
this is what i've tried :
<table>
<thead>
<tr>
{% set now = '' %}
{% set arrKey = [] %}
{% for data in datas %}
{% if now != data.key %}
<th>{{ data.key }}</th>
{% set now = data.key %}
{% else %}
{% set arrKey = arrKey|merge([now]) %}
{% endif %}
{% endfor %}
</tr>
</thead>
<tbody>
{% set rowNow = '' %}
{% for key in arrKey %}
<tr>
{% for data in datas %}
{% if rowNow != dataKey %}
{% if data.value is empty %}
<td>0</td>
{% else %}
<td>{{ data.value }}</td>
{% endif %}
{% set rowNow = data.key %}
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
but this still wrong, it will render :
| A | B | C |
|---|---|----|
| 1 | 0 | 10 |
| 1 | 0 | 10 |
please help me how to solve this?
The best way to manage this is to convert the data inside the controller. This is because the merge filter is a pain to work with. Anyway if you wanted to do it in pure twig, here is how
{% set data = [
{ 'key': 'A', 'value': 1, },
{ 'key': 'A', 'value': 2, },
{ 'key': 'B', 'value': null, },
{ 'key': 'C', 'value': 2, },
{ 'key': 'C', 'value': 4, },
{ 'key': 'A', 'value': 3, },
{ 'key': 'A', 'value': 4, },
] %}
{% set temp = [] %}
{% for row in data %}
{% if not (row.key in temp|keys) %}
{% set temp = temp | merge({ (row.key) : [] }) %}
{% endif %}
{% set temp = temp | merge({(row.key):(temp[row.key]|merge([ row.value, ]))}) %}
{% endfor %}
{% set max = 0 %}
{% for data in temp %}{% if data|length > max %}{% set max = data|length %}{% endif %}{% endfor %}
<table>
<tr>
{% for key in temp|keys %}
<th>{{ key }}</th>
{% endfor %}
</tr>
{% for i in 0..(max-1) %}
<tr>
{% for data in temp %}
<td>{{ data[i] | default(0) }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
demo

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