can't access property of stdClass in TWIG - php

I have googled around and it seems as though the creators of TWIG really insists that what I am doing here, which is to me a pure job for the VIEW, something that the template shouldn't take care of at all?!
I know I can't iterate over an object of stdClass without some custom TWIg filters, so I hacked that for now, but if I can't eve access properties dynamically this TWIG thing really isn't very useful at all.
$fixedModuleNames = array('time', 'date', 'weather'); //since TWIG doesn't iterate over objects by default, this is my solution, don't feel like adding a bunch of twigfilters just for this.
$fixedModules = json_decode($entity->getFixedModules());
/*
Here's what fixedModules look like (although here not JSON but array, before encoded to json, I like to create my JSONs this way in PHP)
$fixedModules["time"] = array(
'show' => true,
'left' => 10,
'top' => 10,
'width' => 100,
'height' => 200,
'fontColor' => '#000000',
'fontSize' => 40,
'fontFamily' => 'Arial',
'borderColor' => '',
'borderRounding'=> 0,
'bgColor' => ''
);
*/
Here's what I am trying to do...
{% for item in fixedModuleNames %}
<TR>
<TD><input type="number" id="left_{{ item }}" value="{{ fixedModules[item].left }}" class="LayoutModuleEditField" /></TD>
So this line fails
{{ fixedModules[item].left }}
There must be a way around this since what I am doing is very routine?

Ah, is this perhaps the preferred way of doing it?
{{ attribute(fixedModules, item).left }}

If your attribute function works then use it.
Consider however fixedModules[item].left. You are asking twig to figure out that item is a variable while left is a constant. Difficult for any system to do to say the least.
I would use something like:
{% for moduleName, module in fixedModules %} {# Time, Date, Weather module #}
{% for itemName,itemValue in module %} {# Process each attribute in the module #}
...
If you want to iterate over an object then just implement the array iterator interface. Usually pretty simple.

item is not the key, but an element of your array. So you can access your attributes this way:
{% for item in fixedModuleNames %}
left = {{ item.left }}
{% enfor %}
If you really want to use the key instead, do something like:
{% for key, item in fixedModuleNames %}
left = {{ fixedModuleNames[key].left }}
{% enfor %}
Hope this helps.

Related

timber/twig how to pass `posts` php-object to JavaScript? Some values are lost

When I'm trying to pass the information contained in {{posts}} I cannot retrieve all of it, at least not the post.link information
{% for post in posts %}
<script>
var t = JSON.parse('{{post|json_encode(constant('JSON_HEX_APOS'))|e('js')}}')
t.link = '{{post.link}}'
console.log(t)
</script>
{% endfor %}
Without manually adding the link, it doesn't show up
Why is this happening and how could I workaround this?
EDIT: related https://github.com/timber/timber/issues/1434
You shouldn’t encode your whole post object. You should encode all the values you need separately.
The link for your post doesn’t show up, because link is not a property, but a method of the Timber\Post object. This might be a little bit confusing, because in Twig we use {{ post.link }}. It looks like it’s a property or maybe an array item. But we could also use {{ post.link() }}, which is the same as {{ post.link }}. You can read more about this in the Variables section in Twig for Template Designers.
So what I would do is build a new array with the data you need and encode it to JSON in PHP with wp_json_encode().
PHP
$posts_json = [];
foreach ( $posts as $post ) {
$posts_json[] = wp_json_encode( [
'title' => $post->title(),
'link' => $post->link(),
] );
}
$context['posts_json'] = $posts_json;
By only adding the data you need, you keep the output in the frontend small. Otherwise, you would end up with a lot of data that you will never and that only increases the page size unnecessarily.
And then in Twig, you could do it like this:
{% for post in posts_json %}
<script>
var t = {{ post }}
console.log(t)
</script>
{% endfor %}

How to get a value of a key in a twig array outside of a loop

I have an array of states and a number like:
(state, count)
states=[
'ACT' => 25,
'NSW' => 45,
'VIC' => 18,
'SA' => 12
]
I'm trying to get the value for each state in twig (outside of a loop).
So for each state (as a dynamic parameter) I need to get the "count" value:
{{ attribute(states, state_name).count }}
or
{{ attribute(states, count)}}
but not working.
Any idea?
Edit:
This code is working but can't get the value out of the loop.
In this code I need to run the loop several times.
{% for state in states %}
{% if state.state_name == state_name %}
({{ state.count }})
{% endif %}
{% endfor %}
There is no variable named count, you only have a key-value array where the value is the count. You can simply use attribute to get the value:
{{ attribute(states, state_name) }}
or, as jeroen commented:
{{ states[state_name] }}

How can I set the route parameter name using a variable in Twig?

I am trying to use the url Twig function with Silex to generate a route, but when I use the variable name that I have passed to the template it generates a warning that I have not supplied the parameter.
This is the array I am passing to the template:
[
"total_pages" => $pages,
"current_page" => $page,
"route_name" => "gallery_album",
"route_parameter" => "groupname",
"route_value" => $groupname
]
And in the template I am trying to use:
{{ url(route_name, {route_parameter: route_value, 'page': page} ) }}
(The page variable value is worked out in the template)
This is part of a pagination template that I am building so I need the parameter to be a variable so it can be applied to different pages. This is the error I get when I run this:
I feel this is something that is very simple, I am just missing something fundamental.
It thinks that route_parameter is a string key name and not a variable:
You can do for example:
{% set params = {'page': page, (route_parameter): route_value } %}
{{ url(route_name, params) }}
You can use {{ app->path}} or {{ app->url }}
if you using Silex\Application\UrlGeneratorTrait in you Application class
or alternative using this
{{ app.url_generator.generate('homepage') }}

Twig Array to string conversion

This is probably relatively easy to do, but I'm new to twig and I'm frustrated.
I'm adapting code from this answer: https://stackoverflow.com/a/24058447
the array is made in PHP through this format:
$link[] = array(
'link' => 'http://example.org',
'title' => 'Link Title',
'display' => 'Text to display',
);
Then through twig, I add html to it, before imploding:
<ul class="conr">
<li><span>{{ lang_common['Topic searches'] }}
{% set info = [] %}
{% for status in status_info %}
{% set info = info|merge(['{{ status[\'display\'] }}']) %}
{% endfor %}
{{ [info]|join(' | ') }}
</ul>
But I'm getting:
Errno [8] Array to string conversion in
F:\localhost\www\twig\include\lib\Twig\Extension\Core.php on line 832
It's fixed when I remove this line, but does not display:
{{ [info]|join(' | ') }}
Any ideas how I can implode this properly?
** update **
Using Twig's dump function it returns nothing. It seems it's not even loading it into the array in the first place. How can I load info into a new array.
info is an array, so you should simple write
{{ info|join(', ') }}
to display your info array.
[info] is a array with one value : the array info.
You shouldn't really be building complex data structures inside of Twig templates. You can achieve the desired result in a more idiomatic and readable way like this:
{% for status in status_info %}
{{ status.display }}
{% if not loop.last %}|{% endif %}
{% endfor %}
You can user json_encode for serialize array as strig, then show pretty - build in twig
{{ array|json_encode(constant('JSON_PRETTY_PRINT')) }}
if need associative array:
{{info|json_encode(constant('JSON_PRETTY_PRINT'))|raw}}

How to check if specific key array element exists?

i have my view in twig
and i have an array which has or hasnt key value i need how to check it if its exist ?
example {{ weather.wind.deg }} and for current moment its possible there is no wind deg so the weather.wind array will not contain an element witch key deg
how to check it if it has it or no ?
maybe i should do it before i past this to my view ?
somewhere here ?
$app->get('/', function () use ($app) {
return $app['twig']->render('index.html.twig', array(
'weather' => $app['weather_service']->get($app['location_service']->get()),
'location' => $app['location_service']->get())
);
});
In you twig template you can do :
{% if weather.wind.deg is defined %}
make your things
{% endif %}

Categories