Twig not working the same as php - php

Why is it that when I write my test in php…
foreach ($rounds as $round){
$assignment = $em->getRepository(‘WorkBundle:Doc’)->findOneBy(array(
‘user’ => $user->getId(),
’whichRound’ => $round,
));
if (!$assignment){
echo “assign ”.$round. “ to user”;
}else{
echo “already assigned to ”.$round. “ to user”;
}
}
return array (
'user' => $user,
'assignment' => $assignment,
'rounds' => $rounds,
);
…it works correctly. When assignment is null, it will output the “assign ”.$round. “ to user”; and when it’s not null it will output “already assigned to ”.$round. “ to user”;.
However when I go in my twig template with the returned variables above and do…
{% for round in rounds %}
{% if assignment is null %}
<h2>{{ user }} successfully added to {{ round }}</h2>
{% else %}
<h2>{{ user }} has already been assigned to the {{ round }}</h2>
{% endif %}
{% endfor %}
…it does not work correctly? It will instead output the same message twice…in an example, if the first round is null and the second one it not null, it will output the second message {{ user }} has already been assigned to the {{ round }} twice.
What am I messing up?

When you go through the foreach loop in your code, you're setting $assignment each time. When you return the array, you're only returning the last time $assignment is set.
It looks like $rounds is an array of numbers and you'd like to associate the round with an assignment result. Based on that, I'd advise building a new array like this:
$results = array();
foreach ($rounds as $round) {
$row = array(
'round' => $round,
'assignment' => $em->getRepository('WorkBundle:Doc')->findOneBy(array(
'user' => $user->getId(),
'whichRound' => $round,
))
);
if ($row['assignment']) {
echo "Already assigned $round to user.";
} else {
echo "Assign $round to user.";
}
$results[] = $row;
}
return array(
'user' => $user,
'results' => $results,
);
Your Twig template would then look like this:
{% for row in results %}
{% if row.assignment is null %}
<h2>{{ user }} successfully added to {{ row.round }}</h2>
{% else %}
<h2>{{ user }} has already been assigned to the {{ row.round }}</h2>
{% endif %}
{% endfor %}

Related

Twig parse array and check by key

I'm trying to see if an array has a key. The first case returns 2 results 1-5 and , while the second seems to work fine.
Any ideea why is this happening ?
{% set options = {'1' : '1' , '1-5' : '5' , '1-12' : '12' } %}
{% set selected = '1-5' %}
Wrong check
{% for k,v in options %}
{% if k == selected %}
{{ k }}
{% endif %}
{% endfor %}
Right
{% for k,v in options %}
{% if k|format == selected|format %}
{{ k }}
{% endif %}
{% endfor %}
https://twigfiddle.com/c6m0h4
Twig will compile the "wrong check" in the following PHP snippet:
if (($context["k"] == (isset($context["selected"]) || array_key_exists("selected", $context) ? $context["selected"] : (function () { throw new RuntimeError('Variable "selected" does not exist.', 6, $this->source); })()))) {
Simplified this becomes
if ($context["k"] == $context["selected"])
Because the type of context["k"] (for the first iteration) is an integer, PHP will typecast the right hand part of the equation to an integer as well. So the equation actually becomes the following:
if ((int)1 == (int)'1-5')
and casting 1-5 to an integer becomes 1, making the final equation to:
1 == 1 which evaluates to true
You can test the fact that first key gets treated as integer with the following PHPsnippet by the way
<?php
$foo = [ '1' => 'bar', ];
$bar = '1-5';
foreach($foo as $key => $value) {
var_dump($key); ## output: (int) 1
var_dump($key == $bar); ## output: true
}
demo

How can I fetch/print the path or url of an entity reference to my twig template (Drupal 8)?

I have been trying to figure out how I can pull the url of a node content type using an entity reference.
Apparently using {{ links.entity.uri }} or {{ links.entity.url }} does not work
<div>
{% for links in node.field_related_items %}
<h2>{{ links.entity.label }}</h2>
<a href="{{ links.entity.uri }} " ></a>
{% endfor %}
</div>
This worked for me:
This will only take you to /node/entity_id though and not /entity_name/entity_id
I would like to expand upon this answer by saying that you should add a Drupal::entityQuery() to your .theme file. Inside of this query, you'll want to grab the "alias" which is the link to the content. In your case this will give you these links /migrations and /aboutiom.
Here's an example of what that might look like...
function theme_name_preprocess_node(&$variables) {
$query = \Drupal::entityQuery('node')
->condition('status', 1)
->condition('type', 'related_links')
$nids = $query->execute();
$nodes = \Drupal\node\Entity\Node::loadMultiple($nids);
$related_links = [];
foreach ($nodes as $item) {
$alias = \Drupal::service('path.alias_manager')->getAliasByPath('/node/'.$item->id());
$related_links[] = [
'title' => $item->getTitle(),
'id' => $item->id(),
'field' => $item->get('field_name')->value,
'alias' => $alias,
];
}
$variables['related_links'] = $related_links;
}
Now in your twig template you can do something like this...
{% for link in related_links %}
{{ link['title'] }}
{% endfor %}

Symfony Undefined variable (contexterror exception) when array empty in controller

Here is the thing. A trainer can speak zero to many languages. I want to display the languages for one or several trainers on a page. Note that I'm working on a code I didn't start from scratch.
In my controller :
foreach ($trainers as $trainer){
$trainer_entity = $doctrine->getRepository('AppBundle:Trainer')->find($trainer["id"]);
$listLangues = $this->getDoctrine()
->getManager()
->getRepository('AppBundle:TrainerLangues')
->findByTrainer_id($trainer["id"]);
}
return [
'user' => $user,
'listLangues' => $listLangues,
'trainers' => $trainers,
];
In my twig file:
{% if listLangues %}
<b>Langues</b> :
{% for l in listLangues %}
{{ l.langue.name }}
{% endfor %}
{% endif %}
This works when the person is linked to languages, so listLangues not empty.
Otherwise I get
Notice: Undefined variable: listLangues 500 Internal Server Error -
ContextErrorException
I tried {% if listLangues is defined %} as well, but the system seems to block in the controller. It never happened to me before.
note that initializing $listLangues only leads to no display on the twig page.
Any idea?
what do you really want to display in your view?
Here is a simple tips, you could try in your controller:
/***/
public function yourAction()
{
return $this->render('your-template.html.twig', [
'user' => $this->getUser(),
'trainers' => $this->getDoctrine()->getRepository(Trainer::class)->findAll()
]);
}
/***/
Then, in your view (basic implementation)
{% for trainer in trainers %}
<h4>{{ trainer.name }}</h4>
{% if trainer.languages %}
<ul>
{% for language in trainer.languages %}
<li>{{ language.name }}</li>
{% endfor %}
</ul>
{% endif %}
{% endfor %}
Hope, it will help you.
If your array $trainers is empty, the foreach nevers loops so the $listLangues var is never defined.
Try declaring it as an empty array BEFORE the foreach :
$listLangues = array();
You need to instantiate $listLangues because if there isn't trainers the variable can't exist and code is broke.
Try to add this before your foreach:
$listLangues = null;
Or instantiate It with a value or what you want but declare It before your foreach to be sure that exists

Cycle through and pull information from array in Twig

I currently have an array full of pre-populated form fields:
$fields = array('title','first_name')
$info = array(
'title' => 'Mr',
'first_name' => 'John',
'last_name' => 'Smith'
)
As you can see this particular fields array only contains the title and first name.
My objective is to cycle through the fields array and see if I have any information in my $info array to pre-populate the field with.
Something like:
foreach (fields as field) {
if (field is in $info array) {
echo the_field_value;
}
}
But obviously in Twig, currently I have something like:
{% for key, field in context.contenttype.fields %}
{% if key in context.content|keys %} << is array
{{ key.value }}<< get the value of the field
{% endif %}
{% endfor %}
Any help is greatly appreciated.
this example dump what you need:
{% set fields = ['title','first_name'] %}
{% set info = { 'title': 'Mr', 'first_name': 'John', 'last_name': 'Smith' } %}
{% for key in fields %}
{% if key in info|keys %}
{{ info[key] }}
{% endif %}
{% endfor %}
Result:
Mr John
Here the working solutions: http://twigfiddle.com/i3w2j3
Hope this help

Symfony2 TWIG show user from know ID

I have a list of tasks stored in the doctrine database which I return like this:
$task = $this->getDoctrine()
->getRepository('SeotoolMainBundle:Tasks')
->findAll();
return array('form' => $form->createView(), 'message' => '', 'list_tasks' => $task);
In one row the ID of and entry from a second table is stored. I don't want only output the ID but also the Name, Description and so on stored in the other table. With normal PHP & MYSQL this would be done by using JOIN - how can I do it with Symfony & TWIG ?
Twig Output:
{% for task in list_tasks%}
{{ task.Id }}
{{ task.TaskTitle }}
{{ task.TaskDescription }}
{{ task.TaskTypes }} /* Here I want not only get the ID but also other fields stored in the database with TaskType ID = task.TaskTypes */
{{ task.User }} /* Here I want not only get the ID but also other fields stored in the database with User ID = task.User */
{% endfor %}
I am assuming that TaskType and User are entities, which belong within the Tasks entity. In which case, try the following. Note that I am getting just one task with id of 1 in my example:
$task = $this->getDoctrine()->getRepository('SeotoolMainBundle:Tasks')->find(1);
$taskTypes = $task->getTaskTypes();
$user = $task->getUser();
return array(
'form' => $form->createView(),
'message' => '',
'list_tasks' => $task,
'task_types' => $taskTypes,
'user' => $user,
);
And in your Twig:
{% for task_type in task_types %}
{{ task_type.Id }} // or whatever fields a task_type has
{% endfor %}
And the same for the user
Edit:
As you are wanting to have ALL tasks processed at once, I wonder if simply the following willl work:
{% for task_list in task_lists %}
{% for task_type in task_list.taskType %}
{{ task_type.Id }} // or whatever fields a task_type has
{% endfor %}
{% endfor %}
I did it now on this way, but I dont think, that it is 100% correct and conform.
How to do better? Luckily this works for me actually:
$task = $this->getDoctrine()
->getRepository('SeotoolMainBundle:Tasks')
->findAll();
$taskTypes = $this->getDoctrine()
->getRepository('SeotoolMainBundle:TaskTypes')
->findAll();
$user = $this->getDoctrine()
->getRepository('SeotoolMainBundle:User')
->findAll();
return array(
'form' => $form->createView(),
'message' => '',
'list_tasks' => $task,
'list_task_types' => $taskTypes,
'list_user' => $user
);
TWIG:
{% for task in list_tasks %}
Task ID: {{ task.ID }} <br/>
{% for type in list_task_types if type.id == task.tasktypes %}
{{ type.tasktypetitle }} <br/>
{% endfor %}
{% for user in list_user if user.id == task.user %}
{{ user.username }} <br/>
{% endfor %}
<hr/>
{% endfor %}

Categories