Hi everyone,
As anyone who has worked with Couch would have noticed, Couch variables have so far been only simple strings or numbers.
A recent conversation with @trendoman led to the development of this feature where now Couch variables can contain multiple values thus acting like Arrays in JavaScript or PHP.
To give you a full context (and also as a lazy way of documenting how this feature works), I am reproducing verbatim the conversation I had with @trendoman.
==================================
Hi Kamran,
How about this
Variation:
================================================
Hi Anton,
Hope you recall the conversation we had some time back regarding 'multi-string' variables (the thread is attached to this message).
I have done some work on the topic
..
..
try out the following in any of your template -
output:
You'll remember, it is one of the example you used earlier.
Point to note is that we are using regular <cms:show> and <cms:capture>.
The only new point above is the use of 'is_json' with cms:capture.
Another of your example -
output:
Again the only new thing is 'is_json' with cms:set.
Rest is regular Couch code.
So news is that now Couch natively supports 'arrays' which makes possible the use of the 'dotted' syntax we saw above.
All the 'setter' tags (cms:set, cms:capture, cms:put), all the 'getter' tags (cms:show, cms:get), all 'conditional' tags(cms:if, cms:else, cms:else_if) and the iterator tag cms:each now recognize 'array' as a valid type.
The syntax for initially setting an array is a valid JSON string with the 'is_json' parameter set to '1'.
Once a variable is set as an array, further interaction with it can be done using the 'dot' syntax alone, as seen above.
Consider the following, for example -
output:
In the example above, the 'my_climate' automatically becomes an array because we used a preexisting array variable (climate.Russia) to set it.
There was no need to use 'is_json' while setting it.
IMP: Using a valid JSON to set an array variable is crucial as anything invalid will result in the variable not getting set at all.
For example, your second example (<cms:set i18 />/> originally had a syntax error and so did not work in the first try. It would be a good idea to use a validator (e.g. https://jsonformatter.curiousconcept.com/ that I did) to first verify the validity of a complex JSON string.
OK, moving on and extending your example a bit further now, try adding this -
output:
Example above shows how we can dynamically add to existing arrays.
To see a textual representation of an array variable (for perhaps debugging), we can ask Couch to spit it out as JSON, as in the following example -
output:
Moving on, all the examples we saw above set values within arrays (e.g. 'Russia', 'India') using 'keys' (e.g. 'Moscow', 'Mumbai' etc.).
If we so wish, we can set values directly without using keys, for example as follows -
As you can see, we are still using the 'dots' but there are no named keys after those.
Internally, Couch automatically creates numeric keys for you (using the last unnamed key) for each unnamed key.
So, in the example above, we actually created the following variables -
output:
Let us take a look at how the array internally looks like -
output:
Let us now see how 'conditionals' work with arrays -
As you can see, we can use the dotted syntax with no problems.
Finally, take a look at how we can use cms:each to iterate through the arrays -
output:
In the example above, the 'climate' variable is an array with three of its keys in turn being arrays themselves.
The cms:each loop correctly reported this (outputting the term 'Array'). The 'Miami' key was a simple variable (i.e. not an array) and so its value was outputted verbatim.
The real meat could be had by looping through the sub-arrays themselves, for example -
output:
output:
To loop through all countries with their cities in our example, we can use the following (shown in two steps for clarity) -
Step 1-
output:
Step 2 -
In the block above that shows we are dealing with an array, add the <cms:each> once again to loop through its descendants like this -
output:
OK, Anton, that is all I have for now. There is a lot more that can be done with arrays (sorting, recursively iterating through all levels etc.) but I have left that for perhaps the future.
..
==============================================
Alright, coming back to present - this is a feature that will be useful as we go ahead and the newer addons begin exposing their data as arrays, So, for example, we could be iterating through cart items as follows -
For now, if anyone is willing to try out this feature, please download Couch from GitHub -
https://github.com/CouchCMS/CouchCMS
Feedback solicited, as always.
Thanks.
As anyone who has worked with Couch would have noticed, Couch variables have so far been only simple strings or numbers.
A recent conversation with @trendoman led to the development of this feature where now Couch variables can contain multiple values thus acting like Arrays in JavaScript or PHP.
To give you a full context (and also as a lazy way of documenting how this feature works), I am reproducing verbatim the conversation I had with @trendoman.
==================================
Hi Kamran,
How about this
- Code: Select all
<cms:capture into='climate'>
{
"Russia" : {
"Moscow" : "cold",
"Sochi" : "warm"
}
}
</cms:capture >
Climate in Moscow: <cms:key 'Russia.Moscow' from=climate />
Variation:
- Code: Select all
<cms:set lang='es' />
<cms:set i18 = '
{
"en" : {
"app" : {
"greet" : "Hello!",
}
},
"es" : {
"app" : {
"greet" : "Hola!"
}
}
}
' />
Maybe a little more advanced parsing:
<h3><cms:key 'i18[lang].app.greet' /></h3>
================================================
Hi Anton,
Hope you recall the conversation we had some time back regarding 'multi-string' variables (the thread is attached to this message).
I have done some work on the topic
..
..
try out the following in any of your template -
- Code: Select all
<cms:capture into='climate' is_json='1'>
{
"Russia" : {
"Moscow" : "cold",
"Sochi" : "warm"
}
}
</cms:capture >
Climate in Moscow: <cms:show climate.Russia.Moscow /><br>
Climate in Sochi: <cms:show climate.Russia.Sochi />
output:
Climate in Moscow: cold
Climate in Sochi: warm
You'll remember, it is one of the example you used earlier.
Point to note is that we are using regular <cms:show> and <cms:capture>.
The only new point above is the use of 'is_json' with cms:capture.
Another of your example -
- Code: Select all
<cms:set i18 = '
{
"en" : {
"app" : {
"greet" : "Hello!"
}
},
"es" : {
"app" : {
"greet" : "Hola!"
}
}
}
' is_json='1' />
<cms:set lang='es' />
<cms:get "i18.<cms:show lang />.app.greet" /><br>
<cms:set lang='en' />
<cms:get "i18.<cms:show lang />.app.greet" /><br>
output:
Hola!
Hello!
Again the only new thing is 'is_json' with cms:set.
Rest is regular Couch code.
So news is that now Couch natively supports 'arrays' which makes possible the use of the 'dotted' syntax we saw above.
All the 'setter' tags (cms:set, cms:capture, cms:put), all the 'getter' tags (cms:show, cms:get), all 'conditional' tags(cms:if, cms:else, cms:else_if) and the iterator tag cms:each now recognize 'array' as a valid type.
The syntax for initially setting an array is a valid JSON string with the 'is_json' parameter set to '1'.
Once a variable is set as an array, further interaction with it can be done using the 'dot' syntax alone, as seen above.
Consider the following, for example -
- Code: Select all
<cms:set my_climate=climate.Russia />
<cms:show my_climate.Sochi />
output:
warm
In the example above, the 'my_climate' automatically becomes an array because we used a preexisting array variable (climate.Russia) to set it.
There was no need to use 'is_json' while setting it.
IMP: Using a valid JSON to set an array variable is crucial as anything invalid will result in the variable not getting set at all.
For example, your second example (<cms:set i18 />/> originally had a syntax error and so did not work in the first try. It would be a good idea to use a validator (e.g. https://jsonformatter.curiousconcept.com/ that I did) to first verify the validity of a complex JSON string.
OK, moving on and extending your example a bit further now, try adding this -
- Code: Select all
<cms:set climate.India='[]' is_json='1' />
<cms:set climate.India.Mumbai='pleasant' />
<cms:set climate.India.Delhi='moderate' />
<cms:set climate.Miami = 'great' />
Climate in Mumbai: <cms:show climate.India.Mumbai /><br>
Climate in Delhi: <cms:show climate.India.Delhi /><br>
Climate in Miami: <cms:show climate.Miami /><br>
output:
Climate in Mumbai: pleasant
Climate in Delhi: moderate
Climate in Miami: great
Example above shows how we can dynamically add to existing arrays.
To see a textual representation of an array variable (for perhaps debugging), we can ask Couch to spit it out as JSON, as in the following example -
- Code: Select all
<cms:show climate as_json='1' /><br>
output:
{"Russia":{"Moscow":"cold","Sochi":"warm"},"India":{"Mumbai":"pleasant","Delhi":"moderate"},"Miami":"great"}
Moving on, all the examples we saw above set values within arrays (e.g. 'Russia', 'India') using 'keys' (e.g. 'Moscow', 'Mumbai' etc.).
If we so wish, we can set values directly without using keys, for example as follows -
- Code: Select all
<cms:set climate.Utopia='[]' is_json='1' />
<cms:set climate.Utopia. = 'unknown' />
<cms:set climate.Utopia. = 'uncertain' />
<cms:set climate.Utopia. = 'finicky' />
As you can see, we are still using the 'dots' but there are no named keys after those.
Internally, Couch automatically creates numeric keys for you (using the last unnamed key) for each unnamed key.
So, in the example above, we actually created the following variables -
- Code: Select all
<cms:show climate.Utopia.0 /><br>
<cms:show climate.Utopia.1 /><br>
<cms:show climate.Utopia.2 /><br>
output:
unknown
uncertain
finicky
Let us take a look at how the array internally looks like -
- Code: Select all
<cms:show climate as_json='1' /><br>
output:
{"Russia":{"Moscow":"cold","Sochi":"warm"},"India":{"Mumbai":"pleasant","Delhi":"moderate"},"Miami":"great","Utopia":["unknown","uncertain","finicky"]}
Let us now see how 'conditionals' work with arrays -
- Code: Select all
<cms:if climate.Russia.Moscow=='cold'>
Cold!
<cms:else />
Warm
</cms:if>
As you can see, we can use the dotted syntax with no problems.
Finally, take a look at how we can use cms:each to iterate through the arrays -
- Code: Select all
<cms:each climate>
<cms:show key /> - <cms:show item /><br>
</cms:each>
output:
Russia - Array
India - Array
Miami - great
Utopia - Array
In the example above, the 'climate' variable is an array with three of its keys in turn being arrays themselves.
The cms:each loop correctly reported this (outputting the term 'Array'). The 'Miami' key was a simple variable (i.e. not an array) and so its value was outputted verbatim.
The real meat could be had by looping through the sub-arrays themselves, for example -
- Code: Select all
<cms:each climate.Russia>
<cms:show key /> - <cms:show item /><br>
</cms:each>
output:
Moscow - cold
Sochi - warm
- Code: Select all
<cms:each climate.India>
<cms:show key /> - <cms:show item /><br>
</cms:each>
output:
Mumbai - pleasant
Delhi - moderate
To loop through all countries with their cities in our example, we can use the following (shown in two steps for clarity) -
Step 1-
- Code: Select all
<cms:each climate>
<cms:if "<cms:is_array item />">
<cms:show key /> (<cms:array_count item />)<br>
<cms:else />
<cms:show key /> - <cms:show item /><br>
</cms:if>
</cms:each>
output:
Russia (2)
India (2)
Miami - great
Utopia (3)
Step 2 -
In the block above that shows we are dealing with an array, add the <cms:each> once again to loop through its descendants like this -
- Code: Select all
<cms:each climate>
<cms:if "<cms:is_array item />">
<cms:show key /> (<cms:array_count item />)<br>
<cms:each item>
<cms:if "<cms:is_array item />">
-- <cms:show key /> (<cms:array_count item />)<br>
<cms:else />
-- <cms:show key /> - <cms:show item /><br>
</cms:if>
</cms:each>
<cms:else />
<cms:show key /> - <cms:show item /><br>
</cms:if>
</cms:each>
output:
Russia (2)
-- Moscow - cold
-- Sochi - warm
India (2)
-- Mumbai - pleasant
-- Delhi - moderate
Miami - great
Utopia (3)
-- 0 - unknown
-- 1 - uncertain
-- 2 - finicky
OK, Anton, that is all I have for now. There is a lot more that can be done with arrays (sorting, recursively iterating through all levels etc.) but I have left that for perhaps the future.
..
==============================================
Alright, coming back to present - this is a feature that will be useful as we go ahead and the newer addons begin exposing their data as arrays, So, for example, we could be iterating through cart items as follows -
- Code: Select all
<cms:each cart_items as='item'>
<cms:show item.price />
<cms:show item.qty />
<cms:show item.discount />
</cms:each>
For now, if anyone is willing to try out this feature, please download Couch from GitHub -
https://github.com/CouchCMS/CouchCMS
Feedback solicited, as always.
Thanks.