Hi guys its rather a very basic question, had chance to look several questions on stackoverflow but all in vain.
so i have this twig variable called "WordoftheDayfromDB ", to which i am passing from some data after querying DB in my controller via laravel pluck method. The controller exsits in plugin of octobercms. the content of the variable is shown below
{% set WordoftheDayfromDB = __SELF__.words %}
{{WordoftheDayfromDB}} # this output below object
["{\"id\":4,\"word_tr\":\"parazit\",\"slug_tr\":\"parazit\",\"word_gr\":\"\\u03c0\\u03b1\\u03c1\\u03ac\\u03c3\\u03b9\\u03c4\\u03bf\",\"slug_gr\":\"parasito\",\"pubordraft\":1,\"created_at\":\"2017-06-07 13:04:57\",\"updated_at\":\"2017-06-07 13:04:57\",\"deleted_at\":null,\"word_image\":\"\\\/cropped-images\\\/image2.jpg\",\"typeswb_id\":0}"]
can someone tell me a way to extract keys and values from the about twig variable.
what i already tried is following:
<pre> {{WordoftheDayfromDB.id}}</pre>
or
{% for item in WordoftheDayfromDB %}
{{item.word_tr}}
{% endfor %}
also some combination using {% if WordoftheDayfromDB is iterable %}.
I will appreciate your answer very much!
thank you for reading my question.
You can use the for loop so that the keys and values are both accessible like this:
{% for key, value in WordoftheDayfromDB %}
<li>{{ key }}: {{ value }}</li>
{% endfor %}
So the answer is rather complex then even i anticipated! i had to do a lot of digging with frustration to really get at the bottom of this matter.
First thing first, i was doing a cron job where i saved the data from a model in text type field. That is why if you see above result i.e
{% set WordoftheDayfromDB = __SELF__.words %}
{{WordoftheDayfromDB}} # this output below object
["{\"id\":4,\"word_tr\":\"parazit\",\"slug_tr\":\"parazit\",\"word_gr\":\"\\u03c0\\u03b1\\u03c1\\u03ac\\u03c3\\u03b9\\u03c4\\u03bf\",\"slug_gr\":\"parasito\",\"pubordraft\":1,\"created_at\":\"2017-06-07 13:04:57\",\"updated_at\":\"2017-06-07 13:04:57\",\"deleted_at\":null,\"word_image\":\"\\\/cropped-images\\\/image2.jpg\",\"typeswb_id\":0}"]
it outputs a JSON String, too bad can't iterate or do something with it.
To solve this,
Create json_decode filter in twig.
Apply the filter to value part of array.
Access Individual values of array with variable[keyname] method.
I created a twig filter json_decode
for creating filter see this Link
while in October, the creation to new twig extension is rather easy which is just give registerMarkupTags method in Plugin.php with filter array poiting to name and function name. See this link for extending twig in octobercms here
Now, the part we were waiting for, how to get the values and show them in twig template. Here it is going to be, by using above same example. This is what i did
{% set wordoftheday = __SELF__.words %}
{% for key, value in wordoftheday %}
{% set decoded = value|json_decode %}
# to get the indvisual values
{{ decoded['id'] }}
{{ decoded['created_at'] }}
{% endfor %}
Related
So I'm trying to build a JSON object in a Twig template and ran into some issues.
Responding to a POST request with something like this from a Twig works fine:
{"urls": ["/a","/b"]}
However if there's invalid json for example a trailing comma, like this;
{"urls": ["/a","/b",,,,,]}
then javascript complains when it receives it (which makes sense as it's invalid).
Doing something like this will always result in invalid JSON because of the trailing comma:
{"urls": [
{% for i in objects %}
"/img/example/'~i.get_url()",
{% endfor %}
]}
Question:
So how do you use Twig to loop over an array of objects and build a valid JSON object?
You can check if is the last loop iteration with the standard cycle twig variable, as example:
{"urls": [
{% for i in objects %}
"/img/example/'{{i.get_url()}}"{% if not loop.last %} , {%endif%}
{% endfor %}
]}
Check this working example
Hope this help
You could create a custom twig filter and output it on the page like :
{{ objects |obj2Json }}
In the filter you could just json_encode the object.
https://symfony.com/doc/current/templating/twig_extension.html
I am trying to dynamically assign variables in Twig inside a loop. For example, this is the JSON being passed into the template:
[{
"name": "firstName",
"value": "Adam",
},
{
"name": "Lastname",
"value": "Human",
}]
It's worth noting, I do not have the ability to modify this JSON formatting, as it's coming from a third party, so I need to solve this problem on the template side.
I want to loop through this json and create variables for each object, like so:
{% for item in json %}
{% set {{item.name}} = item.value %}
{% endfor %}
The challenge is Twig is assumes I'm assigning a value to a literal, when I want to assign the value to a evaluated variable name. This way I can just reference each item in the array like {{firstName}} and get back "Adam" in the template.
I've tried a number of different ways to force Twig to dynamically create a variable array, such as:
{% set (item.name) = item.value %}
and
{% set options = {} %}
{% for item in json %}
{% set options[item.name] = item.value %}
{% endfor %}
With no luck.
Any ideas on dynamically creating variables? This is straight forward in most programming languages, so I'm struggling to understand how this is handled in a template engine like Twig.
If the values are actually iterateable and not a single json string you can put them in an array like:
{% set values = [] %}
{% for item in json %}
{% set values = values|merge({(item.name): item.value}) %}
{% endfor %}
Then you can use values.firstName.
If it is a json string and thus can't be looped through like this. You need to write a basic string parser in twig. I've written something similar like that last week in this answer however. Its a very bad idea in general as it fails on so many occasions.
In Twig with Symfony, to generate a path in a template, it wants to use
{{ path('mypathname', {parameterName: parameterValue}) }}
In my project I have an inherited template, and one block loops through a chunk of data and spits out a list of URL's. What I want to do, is from my new template, is allow me to {% set %} the keyname of the first parameter
so basically like this
template.html.twig
<ul>
{% for thing in things %}
<li>{{ thing.name }}</li>
{% endfor %}
</ul>
otherthings.html.twig
{% extends 'template.html.twig' %}
{% set path_name = "thingDetail" %}
{% set path_param = "id" %}
and see the output like
<ul>
<li>The 20th Thing</li>
</ul>
It may sound ridiculous, but across this app, the naming and pathing styles doesn't always match up with the different kinds of content that goes into that blocks loop, so some type of override needs to happen and the last thing I want to do right now, is overwrite the block for that for each type, when the last thing that needs to be done is URL generation
Thank you!
If you enclose the hash key in parenthesis, Twig will treat it as an expression:
{%- set field = 'foo' -%}
{%- set arr = { (field): 'bar' } -%}
will set arr to
{ foo: 'bar' }
(This is mentioned in the Twig documentation, but it's easy to see how it could be overlooked.)
it's possible to automaticaly convert JSON string variable to array in Twig?
I can use for example this code:
{item.id}
{set array = item.parameters|json_encode()} <-- can i do this automatically for json formatted strings?
{% for parameter in array %}
...
{% endfor %}
But users will write own templates in admin (XML output from e-shop) so I want as few things to learn and understand the code writing. So it's possible to check all variables for JSON syntax and convert to array automaticaly?
Data will be generated from MySQL database directly to template, so there is no controller for between DB result and Twig. I also can't use JSON_TYPE in MySQL because we use old version.
Also i don't looking for something like this (or cusom filter):
{item.id}
{% for parameter in item.parameters|json_encode() %}
...
{% endfor %}
My idea is this:
{item.id}
{% for parameter in item.parameters %}
...
{% endfor %}
(So if there is autoescape in Twig, I am looking for "auto_json_decode" :-) )
Setup:
Twig 1.13.1
PHP 5.4.3
Problem:
I have 10,000 articles in my DB. I need a way to only allow X amount of stories to display on the page. I know I can limit the number in the controller before i call the template but that number will be different depending on the template that is used. I will have one controller to handles all the articles. I need a way to pass the number from the template to the controller to limit the array. I don't want to pull down all 10,000 articles then use twig "slice" filter/func.
I know in django you can use the below. That will only load the top 3 stories.
{% get_latest_stories 3 sports as story_list %}
{% for story in story_list %}
{{ story.title }}
{% endfor %}
Here is my current files.
Controller
<?php
$stories = news_stories::getStories("sports",5); //getStories(section,limit);
?>
<?=$twig->render("storyList.html", array('stories' => $stories))?>
View/Template
{% for story in story_list %}
{{ story.title }}
{% endfor %}
Summary
I would like a way to pass a number from the template to the controller so that i can limit the about of rows returned from the DB
Logically speaking, it would be impossible for the view to pass something to controller since the view is being processed at the end of the stack, after everything else.
You can however, pass a function into the view. You would want to create some sort of getViewStories function that you can access from your twig template. Since you have this already in your controller:
<?php
$stories = news_stories::getStories("sports",5); //getStories(section,limit);
?>
<?=$twig->render("storyList.html", array('stories' => $stories))?>
All you would need to do is change it around a bit, like this:
<?php
$function = new Twig_SimpleFunction('getViewStories', function (section, limit) {
return news_stories::getStories(section,limit);
});
$twig->addFunction($function);
?>
<?=$twig->render("storyList.html")?>
Now, from inside your template, you can call this function, like so:
{% set story_list = getViewStories('sports',5) %}
{% for story in story_list %}
{{ story.title }}
{% endfor %}
And change the getViewStories parameters around in each template.
And while you can use the slice filter, I would recommend against it in your case, as it makes for unnecessarily long database calls. This is the most optimized method (that I'm aware of).
You want to use the slice filter I think this should work for you
http://twig.sensiolabs.org/doc/filters/slice.html
{% for story in story_list|slice(1,5) %}
{{ story.title }}
{% endfor %}
should only return the elements 1 - > 5 of the loop then break loop. You can also do it like this
{% for story in story_list|[start:5] %}
{{ story.title }}
{% endfor %}
Disclaimer: I've never actually used twig though this was just a quick browse through its docs
You can embedded controllers ( or render other urls ) from inside a twig template. This means you could have a main layout template for your site, and keep your storyList.html template very plain - just to iterate over the stories and any markup they might need.
In your main layout you would render the action for the news stories:
<div id="stories">
{% render url('...') with { section: 'sports', limit: 5}, {'standalone': 'js'} %}
</div>
This way requires hindclude.js included on your page. Check these docs. If you are also using symfony ( you mention MVC but not the framework ) - even better. Scroll up a bit and look at Embedded controllers.
Otherwise, I believe this way essentially uses ajax.