How to use a dynamic smarty variable in foreach loop - variables

Can anyone tell me how to use dynamic variables in smarty foreach loop. I am trying to create a module in prestashop and m very close to get it done.
here's my code:
//file name index.php
foreach( $subCategories as $s )
{
$foo = intval($s['id_category']);
$k = new Category($foo);
$var1 = "subSubCategories.$foo";
$var1 = $k->getSubCategories(1);
$smarty->assign(array('foo'.$foo => $var1));
}
//file name:index.tpl
{assign var=foo value=$foo$cat}
//where $cat is a variable that counts the number of categories
{if isset($foo) AND $foo}
{foreach from=$foo item=subCategories name=homesubCategories}
<p>{$subCategories.name}</p>
{/foreach}
{else}
<p>{l s='test failed'}</p>
{/if}
I've exhausted all of my resources and knowledge and feeling quite helpless at this moment. so plz help me out.
I am trying to create dynamic variables ('foo'.$foo i.e. foo1, foo2, and so on) depending on the number of sub-categories. I think m successful up to this point. Now moving on to the tpl file, here I want to access the dynamically created variable (foo2, foo3 etc.) using foreach. Now if I am doing this: {assign var=foo value=$foo3} I succeed in fetching the values from this subcategory using the same foreach loop. But when I do this: {assign var=foo value=$foo$catx} (where $catx stores the values for category id) it fails. Please help.

I use such code in section loop (for Smarty 2):
{section name=buildings loop=7 start=1 step=1 max=7}
<tr>
{assign var=part_number value="part`$smarty.section.buildings.index`_number"}
<td class="number">
<input class="number xshort" name="part{$smarty.section.buildings.index}_number" value="{$data.$part_number}" type="text">
</td>
</tr>
{/section}
As you can see, there are a creation of dynamic variable part_number (see backticks in value block). And then, you can use it as value="{$data.$part_number}".

Your $smarty->assign() call is incorrect; you've only got one parameter being sent to it, but it needs two parameters (the variable name, followed by the value). Based on your template code (looping through variable $foo), your loop should be something like this in PHP:
//file name index.php
$subcats = array();
foreach($subCategories as $s) {
$foo = intval($s['id_category']);
$k = new Category($foo);
$subcats[$foo] => $k->getSubCategories(1);
}
$smarty->assign('foo', $subcats);
Then it also looks like you're not using the Smarty {foreach} quite properly either. You're declaring the name attribute, of the foreach loop, but then not using it properly. Assuming $k->getSubCategories(1) returns a string, the smarty code would just have to be:
{foreach from=$foo item=subCategories}<p>{$subCategories}</p>{/foreach}
If $k->getSubCategories(1) returns an array with a 'homesubCategories' element (which is what I think you're trying to get at with your Smarty code), you still don't need the 'name' value on the foreach. You'd then just do:
{foreach from=$foo item=subCategories}<p>{$subCategories.homesubCategories}</p>{/foreach}

With $foo = intval($s['id_category']); you defined $foo as an integer.
Then you concat the string with $smarty->assign(array('foo'.**$foo** => $var1));
Correct is:
$foo = $s['id_category'];
$smarty->assign(array('foo'.$foo => $var1));

Dynamically named variables are generally a very bad design choice, making everything much more difficult than it needs to be.
If you have a set of elements you need to loop over or index into, put them in an array; then you don't need to do any magic assignments, as you can use normal foreach loops or array key access:
//file name index.php
// Build the array first, then assign it to Smarty at the end
$foo_array = array();
foreach($subCategories as $s)
{
$foo = intval($s['id_category']);
$k = new Category($foo);
// This line is redundant as you over-write on the following line:
// $var1 = "subSubCategories.$foo";
$var1 = $k->getSubCategories(1);
$foo_array[ $foo ] = $var1;
}
// Assigning one variable, so just pass name and value to $smarty->assign()
$smarty->assign('foo_array', $foo_array);
//file name:index.tpl
{* Look for the entry in the outer array with key "$cat", then loop over it *}
{foreach from=$foo_array[$cat] item=subCategories}
<p>{$subCategories.name}</p>
{/foreach}

it's possible to call variable dynamically created in template with this statement:
if for example $index = 2
{$foo{$index}}
then this will call variable with name {$foo2}

Related

ErrorException [ Notice ]: Undefined variable on an existing variable dynamically built

First of all thanks for your time on my issue.
Second sorry if this is a duplicate, I legit searched for 3 days on and off and didn't find answer to my particular situation.
Visual on the error obtained
This first line transforms an array's values into a string of index(es)
$path = self::extract_path($path);
After extraction $path becomes a string with a format similar to['key1']['key2']
Here I test if one valuable element (ondemand) is found within that Keys string, so far so good.
if( $path !== FALSE && strpos($path, $element) !== FALSE){
$var_dim_str = 'coupon' . $path . '[recurrence]';
As a self-proofing, I hard-coded one of my specific scenario element and it does exist so my issue is not really non-initialization of my variable as most other topic were suggesting.
var_dump($coupon['item']['ondemand']['recurrence']);
My issue lies here, I get "ErrorException [ Notice ]: Undefined variable: coupon[item][ondemand][recurrence]"
$recurrence = $$var_dim_str;
[...]
Here are my var_dump output:
These are my indexes as an array they get extracted to reconstruct the variable's string', I have some variable-dimension arrays that gets called so the dimension depth might not always be of fixed value, hence why I have to dynamically test this.
1- $path, before being extracted
[...]\modules\payment\classes\Helper\Payment.php:290:
array (size=2)
0 => string 'item' (length=4)
1 => string 'ondemand' (length=8)
2- We see here that (['item']['ondemand']['recurrence'] => 3) exists
[...]\modules\payment\classes\Payment\Cart.php:266:
array (size=1)
'item' =>
array (size=3)
'ondemand' =>
array (size=14)
[...]
'recurrence' => string '3' (length=1)
[...]
3- My var_dump above is outputting it properly.
[...]\modules\payment\classes\Payment\Cart.php:270:string '3' (length=1)
**So, my conclusion is that PHP doesn't really appreciate my 'built' variable but there has to be some way to make this logic work... any pointers on this would be really appreciated. **
The issue does lie with $$var_dim_str. What the $$ does is resolve $$variableName to be the variable name contained in $variableName. It basically holds a reference to another variable based on the variable's name. From the PHP site:
A variable variable takes the value of a variable and treats that as the name of a variable. In the above example, hello, can be used as the name of a variable by using two dollar signs. i.e.
So ...
// some variables
$name = 'Ellan' ;
$site = 'Stack Exchange' ;
$tags = 'PHP-7, Variables' ;
// we want $site
$variableName = 'site' ;
echo $$variableName ;
// we want $tags
$variableName = 'tags' ;
echo $$variableName ;
The code above will produce:
Stack Exchange
PHP-7, Variables
When you assign a value to $var_dim_str:
$var_dim_str = 'coupon' . $path . '[recurrence]';
$var_dim_str does not hold the name of a variable. It contains the a string.
Are you sure you want to use $$ in this instance? Maybe you really want to use:
$recurrence = $var_dim_str;

CDbMigration::update does not work inside foreach loop

Following this question. There is something wrong, when using CDbMigration::update() inside foreach loop.
This code does not work correctly:
//This is executed inside Yii migration, so $this is CDbMigration.
foreach($idMap as $menuId=>$pageId)
{
$this->update
(
'menus_items',
array('link'=>'/content/show?id='.$pageId),
array('id = '.$menuId)
);
}
For each item in $idMap value of $pageId is always the same and equals value of last item in $idMap array. Therefore, every menu item points to the same URL.
This code works like a charm:
foreach($idMap as $menuId=>$pageId)
{
$sql = "UPDATE `menus_items` SET link = '/content/show?id=".$pageId."' WHERE id = ".$menuId."; ";
Yii::app()->db->createCommand($sql)->execute();
}
For each item in $idMap value of $pageId is always different and equals value of current item in $idMap array. Therefore, every menu item points to correct URL.
The same goes, when executing all statements in one SQL query:
$sql = '';
foreach($idMap as $menuId=>$pageId)
{
$sql .= "UPDATE `menus_items` SET link = '/content/show?id=".$pageId."' WHERE id = ".$menuId."; ";
}
Yii::app()->db->createCommand($sql)->execute();
Again, everything is OK.
Why using CDbMigration::update() fails, while direct SQL execution works like a charm?
I don't think you are providing the criteria parameter properly # array('id = '.$menuId)
. You should use a string if you want to send it like that, putting it in an array presumes you are mapping out the conditions in a key => value pair. Also you should be wrapping the value constraint in quotes id = "$menuId".

handlebars returning index along with data

I have a helper that loops through jason data till a given value and sends the data back to the template.I also want to show at what location the data is present (the index), is there any way where in i can return the Index value along with the data?
Handlebars.registerHelper('print_range', function(items,count,options)
{
var out = "";
for(var i=0, l=items.length; i<count; i++)
{
out = out + options.fn(items[i]);
}
return out;
});
<script id="template" type="text/x-handlebars-template">
{{#print_range options "2"}}
<h1>index</h1> // this index should correspond to i in the helper function
<h2>{{optionID}}{{nextID}}</h2>
{{/print_range}}
</script>
Thanks in advance.
Handlebars.registerHelper('print_range', function(items,count,options)
{{#print_range options "2"}}
Not sure 100% what you're asking, but i do see a problem in your code. You specify 3 parameters in the function, but only give it 2 in your statement call to the helper.
{{#print_range options "2"}}
^ fn name ^items ^ count
Where's the value for your options variable? In handlebars, the parameters for the function go in order after the helper name you are calling

construct variable names dynamically in velocity

I would like to know if it is possible to construct name of variable into velocity dynamically.
i.e. lets say I've 6 variables into velocity template [name1, name2, name3 .. name6] I would like to output them.
So I'm looking in something like:
#foreach ( $counter in [1..6] )
${name${counter}}
#end
is it possible somehow?
It is possible using the #evaluate directive:
#evaluate ('$name1')
#set ($d = '$')
#foreach ($i in [1..6])
#set ($varName = "${d}name${i}")
#evaluate($varName)
#end
You could construct a map and build the names of the keys to retrieve the values you want:
#set( $map = {"${name}1":'value1', "${name}2":'value2'} )
#foreach ( $counter in [1..6] )
#set( $key = "${name}$counter" )
$map.get(${key})
#end
Here is a trick to set velocity variable with dynamic name.
If you manage to tune velocity context beforehand in java code like this:
VelocityContext context = new VelocityContext(paramsMap);
context.put("all", paramsMap);
then it would be possible to define dynamic vars in template like this:
#set($dynamicDef = "varName=varValue")
#set($dynamicName = $dynamicDef.substring(0, $dynamicDef.indexOf('=')))
#set($dynamicValue = $dynamicDef.substring($dynamicDef.indexOf('=')).substring(1))
## create var with dynamic name
$all.put($dynamicName, $dynamicValue)
and use them later like this:
#if ($varName)
varName=$varName ## prints varName=varValue
#end

Dynamic variable different for every Wordpress post: how to declare in loop?

I need a wordpress loop that for every post checks a meta numeric variable previously assigned to each of the taxonomies of the post and returns the sum of these meta variables.
To do so, I think I need a dynamic variable name for the total. I mean something like:
variablerelatedtopost = metataxonomy1 + metataxonomy2 + ... + metataxonomyn
echo variablerelatedtopost
How can I do that? Is it possible to generate a dynamic numeric variable via loop? and HOW can I refer to it in a general way, without adressing it with its name?
Thanks everyone! And sorry for possible English mistakes :P
EDIT: I just realized the code by Alex is not what I wanted. I need a variable which changes name at every post and which value is always = 0. Is there a solution?
can you not just add a counter to your loop like this?
//Total should start # 0 before the loop
$total = 0;
// The Query
$the_query = new WP_Query($args);
// The Loop
while ( $the_query->have_posts() ) : $the_query->the_post();
$amount = get_post_meta($post->ID, 'the_meta_data_field', true);
$total = $total + $amount;
endwhile;
//echo total
echo $total;
I found the solution to my problem: an array which increases its lenght at every cicle of the loop. I know it's simple but since I'm just a beginner it took me a while to think about it. I post the code here so maybe it can help someone (and if you find bugs or have improvements, please tell me)
//Before the loop, empty array
$totale = array();
// WP Loop
while ( $loop->have_posts() ) : $loop->the_post();
$totale[] = 0;
$indice = (count($totale)) - 1;
// $termvariable was previously set up as a term meta value
if( has_term( 'numberofterm', 'nameoftaxonomy' ) ) {
$totale[$indice] = $termvariable + $totale[$indice];
}