I'm new to Symfony, so this is most certain a simple mistake from my side.
I get the following error: Variable "worker" does not exist.
The template looks like this:
{% extends "NTSBSServiceBundle::layout.html.twig" %}
{% block body %}
<h1>Rapportera</h1>
{% for worker in workers if workers %}
{{ worker.name }}
{% else %}
<em>Det finns inga öppna protokoll för närvarande...</em>
{% endfor %}
{% endblock %}
And the controller method look like this:
/**
* List all open protocols, grouped by worker.
*
* #Route("/", name="report")
* #Method("GET")
* #Template()
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$workers = $em->getRepository('NTSBSServiceBundle:Worker')->findAll();
return array(
'workers' => $workers,
);
}
I have checked, and $workers does contain entities from the database. The twig gets rendered. If I remove the for-loop, naturally the error message disappears.
Hoping that someone can explain to me what I'm doing wrong.
UPDATE:
Have confirmed that the correct controller is used by exiting in indexAction(). If i do a print_r of $workers, I get the following output:
Array
(
[0] => NT\SBSServiceBundle\Entity\Worker Object
(
[id:NT\SBSServiceBundle\Entity\Worker:private] => 2
[name:protected] => Worker 1
[mail:protected] => worker1#example.com
[phone:protected] => 123456789
)
[1] => NT\SBSServiceBundle\Entity\Worker Object
(
[id:NT\SBSServiceBundle\Entity\Worker:private] => 3
[name:protected] => Worker 2
[mail:protected] => worker2#example.com
[phone:protected] => 123456789
)
)
Also I have tried to change the rendering-method by changing from annotation to using the render-method, as such:
return $this->render('NTSBSServiceBundle:Report:index.html.twig',array( 'workers' => $workers ));
You can not do {% for i in x if x %}
You have to do
{% if x | length > 0 %}
{% for i in x %}
instructions
{% endfor %}
{% endif %}
Use twig doc : http://twig.sensiolabs.org/doc
I do always loop through arrays in Twig like that:
{% for b in books %}
{{ b.name }}
{% endfor %}
{% if not books %}
<i>{% trans %}utils.nothing{% endtrans %}</i>
{% endif %}
But your error looks like a variable is missing. What is your error message?
Symfony2 Variable “name” does not exist
or
Variable "worker" does not exist.
Related
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
I have an array of user records (0 indexed, from a database query), each of which contains an array of fields (indexed by field name). For example:
Array
(
[0] => Array
(
[name] => Fred
[age] => 42
)
[1] => Array
(
[name] => Alice
[age] => 42
)
[2] => Array
(
[name] => Eve
[age] => 24
)
)
In my Twig template, I want to get all the users where the age field is 42 and then return the name field of those users as an array. I can then pass that array to join(<br>) to print one name per line.
For example, if the age was 42 I would expect Twig to output:
Fred<br>
Alice
Is this possible to do in Twig out of the box, or would I need to write a custom filter? I'm not sure how to describe what I want in a couple of words so it may be that someone else has written a filter but I can't find it by searching.
Final solution was a mix of what has been posted so far, with a couple of changes. The pseudocode is:
for each user
create empty array of matches
if current user matches criteria then
add user to matches array
join array of matches
Twig code:
{% set matched_users = [] %}
{% for user in users %}
{% if user.age == 42 %}
{% set matched_users = matched_users|merge([user.name|e]) %}
{% endif %}
{% endfor %}
{{ matched_users|join('<br>')|raw }}
merge will only accept an array or Traversable as the argument so you have to convert the user.name string to a single-element array by enclosing it in []. You also need to escape user.name and use raw, otherwise <br> will be converted into <br> (in this case I want the user's name escaped because it comes from an untrusted source, whereas the line break is a string I've specified).
In twig you can merge the for ( .... in ....) with the if condition like :
{% for user in users if user.age == 42 %}
{{ user.name }}{{ !loop.last ? '<br>' }}
{% endfor %}
Edit: This syntax is deprecated, and we are advised to use |filter as a replacement for the for...if syntax.
Twig Filter: filter (The name of the filter is filter)
Twig Deprecated Features
You can apply a filter on the array you apply for loop on, like this:
{% for u in user|filter((u) => u.age == 42) -%}
<!-- do your stuff -->
{% endfor %}
{% for user in users %}
{% if user.age == 42 %}
{{ user.name|e }}<br>
{% endif %}
{% endfor %}
in alternative you can create an array of elements
{% set aUserMatchingCreteria %}
{% for user in users %}
{% if user.age == 42 %}
{% aUserMatchingCreteria = aUserMatchingCreteria|merge(user.name) %}
{% endif %}
{% endfor %}
{{ aUserMatchingCreteria|join('<br>') }}
Since Twig 2.10, the recommended way to conditionally exclude array elements is the filter filter. As was noted in some previous answers, loop.last has some issues, but you can simply flip the logic and use loop.first, which will work consistently:
{% for user in users|filter((u) => u.age == 42) %}
{{ loop.first ?: '<br/>' }}
{{ user.name|e }}
{% endfor %}
I am using twig files for some of the forms in my PHP application. I did everything following this link
http://twig.sensiolabs.org/doc/extensions/i18n.html#
which tells how twig files can be translated using Twig_Extensions_Extension_I18n. I believe i have followed all the steps but still i cannot seem to solve the problem.
This is how my PHP code looks like
require_once 'Twig/Autoloader.php';
Twig_Autoloader::register();
$twig_loader = new Twig_Loader_Filesystem(APP_PATH . 'corporate/views');
$GLOBALS['twig'] = new Twig_Environment($twig_loader, array(
'cache' => TMP_PATH . 'twig_cache',
'debug' => DEBUG,
'auto_reload' => true
));
$GLOBALS['twig']->addExtension(new Twig_Extensions_Extension_I18n());
return $GLOBALS['twig']->
render('path/to/twig/template'.$formTemplate,
array_merge($formVariables,
array(
"help" => isset($helpbox) ? $helpbox : array(),
"type" => $current_data['type'],
"integration_id" => $current_data['action_comp'],
"automation_type" => $current_data['automation_type']
)
)
);
There is another PHP file where i read all the twig files and run the following command as following.
$exe = 'xgettext --force-po --default-domain emarketeer --keyword="pgettext:1c,2" -c -j -o /tmp/messages.po '.escapeshellarg($file).' >/dev/null 2>&1';
system($exe);
this is how my twig template ($formTemplate) looks like
{% extends 'integrations/_mixed/automation_form_wrapper.twig' %}
{% block formular %} {% import "_utils/form.twig" as form %}
{{ form.boxlabel( 'Name (choose automation Name)'|trans, "Name") }}
{{ form.input("action_name", action_name.value, "", "",
action_name.collection ) }}
{% endblock %}
The imported twig template ('_utils/form.twig') as form looks like this
{% macro boxlabel(label, label_for, tooltip, class, extra) %} {% set
label_parts = label|split("\n") %} {{- label_parts[0] -}} {% if tooltip %} {% endif %} {% if label_parts[1] %}
{{ label_parts[1]}} {%
endif %} {% endmacro %}
{% macro input(name, value, type, class, extra) %}
{% endmacro %}
Can anyone please tell me if i am missing something. There will be a lot of code which i cannot defin or explain but i hope i have delivered the idea and the question. Any help would be greatly appreciated.
I have an array like this:
array['a'] = {x => 1, y => 2...}
array['b'] = {x => 5, y => 7...}
I need to iterate over the array, but in each case I need to enter only in the 'a' or 'b' which I choose.
{% for i in main %}
{% set id = i.getId %}
{% for j in array.id %}
//do something like j.propertyA ...
{% endfor %}
{% endfor %}
The fail is always get the error: "The key 'id' for array with keys 'a', 'b'... does not exist"
If I force writting:
{% for j in array.a %}
The program works fine always with array.a but I need to works with all automatically.
Any idea? Thanks :)
Change {% for j in array.id %} to {% for j in array[id] %}
This is because you're trying to access "id" (as is written) directly from array (and isn't defined). With [id] your variable is substitued with its value and so your call will not fail
I think you need array|keys twig filter. See more: http://twig.sensiolabs.org/doc/filters/keys.html.
I have 2 TWIG renderblock's working on a base and standard template. The two blocks render on the page, everything before {% extends "base.php" %} and after {% block body %}{% endblock %} in base.htm does not render, I see why as I have used renderblock not render which should render the whole template. 1 how do I get whole template to render and 2. {% block head %} will not render unless I use a for loop, I am sure there is a better way of doing this. Edit 1: added $data2.
API
$template = $twig->loadTemplate('event.htm');
echo $template->renderBlock('head', (array('heads' => $data2)));
echo $template->renderBlock('content', (array('events' => $data)));
base.htm
<html>
<head>
{% block head %}
{% for head in heads %}
<title>{{ head.title }}</title>
<meta charset="UTF-8">
</head>
<body>
<h1>{{ head.title2 }}</h1>
{% endfor %}
{% endblock %}
{% block body %}{% endblock %}
</body>
</html>
event.htm
{% extends "base.php" %}
{% block content %}
{% for event in events %}
{{event.uri}}
{{event.desc}}
{% else %}
no events!
{% endfor %}
{% endblock %}
$data2
Array ( [0] => Array ( [id] => 1 [uri] => /event1/1 [title] => some title ) )
1/ As soon as you are rendering a block, you get the content of that block, nothing more.
You need to render the whole template using:
$template = $twig->loadTemplate('event.htm');
echo $template->render(array(
'heads' => $data2,
'events' => $data,
));
2/ You need to use a loop because there are big chances $data2 contains an array or an object instead of the expected header. You should use a string instead, or know in which index you can access your header. This is difficult to help you as I don't know what does contain your $data2 variable, but an ugly solution could be to use the reset function this way:
echo $template->render(array(
'heads' => reset($data2),
'events' => $data,
));
2/ If you know which index (in this case 0) as suggested by Alain
echo $template->render(array(
'heads' => $data2[0],
'events' => $data,
));