Home > Net >  Smarty foreach result grouped and concatenate
Smarty foreach result grouped and concatenate

Time:04-07

I have a multidimensional array and would like to generate a definition list grouped by name and values concatenated comma separated.

Through the smarty foreach loop, I manage to generate a definition list but was unable to group by the name nor concatenate the respective values.

The array looks like this:

Array ( 
    [0] => Array ( 
        [name] => Fabric 
        [value] => Silk 
    ) 
    [1] => Array ( 
        [name] => Paper 
        [value] => A4 
    ) 
    [2] => Array ( 
        [name] => Paper 
        [value] => A5 
    ) 
)

The smarty foreach loop:

<dl>
    {foreach from=$products item=feature}
        <dt>{$feature.name}</dt>
        <dd>{$feature.value}</dd>
    {/foreach}
</dl>

So far I just managed to get a definition list like this:

<dl>
    <dt>Fabric</dt>
    <dd>Silk</dd>
    <dt>Paper</dt>
    <dd>A4</dd>
    <dt>Paper</dt>
    <dd>A5</dd>
</dl>

This is how I need to get it:

<dl>
    <dt>Fabric</dt>
    <dd>Silk</dd>
    <dt>Paper</dt>
    <dd>A4, A5</dd>
</dl>

Any help would be greatly appreciated.

I forgot to mention that I can't change the array. I have to solve this in the .tpl file.

CodePudding user response:

To do it at the template level you can create an array using the following syntax to group the products by name:

{foreach from=$products item=feature}
    {$grouped[$feature.name][] = $feature.value}
{/foreach}

Then in your foreach add a reference to the key which is the product name and implode the values:

<dl>
    {foreach from=$grouped key=$key item=features}
        <dt>{$key}</dt>
        <dd>{", "|implode:$features}</dd>
     {/foreach}
</dl>

CodePudding user response:

// Setup:
$products = 
[
    ['name' => 'Fabric', 'value' => 'Silk'],
    ['name' => 'Paper', 'value' => 'A4'],
    ['name' => 'Paper', 'value' => 'A5'],
];

First lets group your products by name with function:

function groupByKeys($array) 
{
    $result = [];
    
    foreach($array as $key => $value) {
        if(!array_key_exists($value['name'], $result)) {
            $result[$value['name']] = [];
        }
        
        $result[$value['name']][] = $value['value'];
    }
    
    return $result;
}


$groupedproducts = groupByKeys($products);

Then just show them in template, values comma separated:

<dl>
    {foreach from=$groupedproducts key=k item=v}
        <dt>{$k}</dt>
        <dd>{', '|implode:$v}</dd>
    {/foreach}
</dl>
  • Related