In Symfony I am using a query to retrieve all questions and their relative answers from a database. Using a for in twig I am trying to display in a table all questions with the relative answers row by row. At the moment I am able to access and display the questions only but not the answers.
The relation between my entities Questions and Answers is (one to many) thus when retrieving the question, also the answers are retrieved. Using dump, I can see the the answers are put in an Array Collection.
Trying to get only a single question from the database with another query, using the getAnswers() function from my Question entity I am able to get the answers from the array collection using this statement:
$answer = $question->getAnswers()->getValues();
Using this statement I tried to get the answers for all the questions using the bellow code in the controller, but I get this error:
Error: Call to a member function getAnswers() on a non-object
I believe this is because the query returns multiple questions and not just one.
How can I get the answers for each individual question from the Array Collection? Thanks in advance for the help.
Controller Code:
$question = $this->getDoctrine()
->getRepository('QuizBundle:Question')
->findByIdJoinedToCategory();
return $this->render('QuizBundle:Default:admin.html.twig', array('data' => $question));
Question Repository:
public function findByIdJoinedToCategory()
{
$query = $this->getEntityManager()
->createQuery(
'SELECT a, q FROM QuizBundle:Question a
JOIN a.answers q');
try {
return $query->getResult();
} catch (\Doctrine\ORM\NoResultException $e) {
return null;
}
}
Twig Code:
{% for item in data %}
<tbody>
<tr>
<th scope="row">{{ item.id }}</th>
<td>{{ item.image }}</td>
<td>{{ item.question }}</td>
<td></td>
<tr>
<tbody>
{% endfor %}
Dump screenshot of the data from the query:
With Twig and according to your doctrine query, you can display your questions/answers like this :
{% for item in data %}
<tbody>
<tr>
<th scope="row">{{ item.id }}</th>
<td>{{ item.image }}</td>
<td>{{ item.question }}</td>
{% for answer in item.answers %}
{{ answer.id }}
{% endfor %}
<tr>
<tbody>
{% endfor %}
Btw, if it exists a relation between the two entities Question and Answer and you want to display all the questions and their associative answers, you can directly doing this :
In your controller:
$questions = $this->getDoctrine()
->getRepository('QuizBundle:Question')->findAll();
return $this->render('QuizBundle:Default:admin.html.twig', array('data' => $questions));
In your Twig :
{% for question in data %}
<tbody>
<tr>
<th scope="row">{{ question.id }}</th>
<td>{{ question.image }}</td>
{% for answer in question.answers %}
{{ answer.id }}
{% endfor %}
<tr>
<tbody>
{% endfor %}
Related
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 %}
Whenever I check the "wetsoil" checkbox, my search results correctly filter through and display all the plant species that grow in wet soil, but whenever I don't check the checkbox, there are no search results. I want all the objects to appear if the checkbox is unchecked, not none of them. Not sure if my logic is incorrect, or maybe my syntax? In the database, "x" means yes.
My controller:
public function SearchResultsAction(Request $request)
{
$botanicalname = $request->query->get('botanicalname');
$commonname = $request->query->get('commonname');
$wetsoil = $request->query->get('wetsoil');
$repository = $this->getDoctrine()->getRepository('AppBundle:Shrubs');
$query = $repository->createQueryBuilder('p');
$shrubs = $query
->where($query->expr()->like('p.botanicalname',':botanicalname'))
->setParameter('botanicalname', '%'.$botanicalname.'%')
->andwhere($query->expr()->like('p.commonname',':commonname'))
->setParameter('commonname', '%'.$commonname.'%')
->andWhere($query->expr()->like('p.wetsoil',':wetsoil'))
->setParameter('wetsoil', $wetsoil)
->orderBy('p.commonname', 'ASC')
->getQuery()
->getResult();
return $this->render('shrubs/searchresults.html.twig', array(
'shrubs' => $shrubs,
));
}
And my input on the HTML page:
<label for="wetsoil">Tolerates Wet Soil: </label>
<input type="checkbox" name="wetsoil" value="x">
Note: I chose not to use the standard Twig syntax ({{ form_widget(form.wetsoil) }}) due to other technical reasons.
Front end:
<table class="table table-striped">
<thead>
{% if shrubs | length == 0 %}
<h3>No species match your search criteria. Try again.</h3>
{% else %}
<tr>
<th>Common Name</th>
<th>Botanical Name</th>
</tr>
</thead>
<tbody>
<tr>
{% endif %}
{% for shrub in shrubs %}
<td>{{ shrub.commonname }}</td>
<td>{{ shrub.botanicalname }}</td>
{#<td>#}
{#<ul>#}
{#<li>#}
{#show#}
{#</li>#}
{#<li>#}
{#edit#}
{#</li>#}
{#</ul>#}
{#</td>#}
</tr>
{% endfor %}
</tbody>
</table>
Suppose I have an entity class named Userinfo where the fields are name, guid, status...
So now from a twig page if i want to show all available name from the entity class Userinfo, how i can do that.
as an example --- in the page there can a table where it will show -- name and status.
So from entity class Userinfo all the names and their status will be shown.
Can someone knows how to dynamically show the data into the twig page from an entity class, can you kindly give me an example if possible.
Plain and simple, you pass the collection to the template:
public function someAction()
{
$usersInfos = $this->getDoctrine()
->getRepository('YourBundle:UserInfo')
->findAll();
return $this->render('YourBundle:your_template.twig', array(
'usersInfos' => $usersInfos
));
}
To render a table in your_template.twig
<table>
<thead>
<th>name</th>
<th>guid</th>
<th>status</th>
</thead>
<tbody>
{% for userInfo in usersInfos %}
<tr>
<td>{{ userInfo.name }}</td>
<td>{{ userInfo.guid }}</td>
<td>{{ userInfo.status }}</td>
</tr>
{% else %}
<tr>
<h2>Empty!</h2>
</tr>
{% endfor %}
</tbody>
</table>
Example
Contoller
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('YourBundle:Entity')->findAll();
return $this->render('YourBundle:index.html.twig', array('entities ' => $entities ));
}
Twig
{% for entity in entities %}
{{ entity.name }}<br>
{% endfor %}
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 :/
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;
}