
本文介绍如何在不修改原始 php 数据的前提下,仅通过 smarty 模板语法对多维数组按指定键(如 name)分组,并将同组的 value 值以逗号连接后渲染为定义列表(<dl>),适用于 smarty 3+ 版本。
本文介绍如何在不修改原始 php 数据的前提下,仅通过 smarty 模板语法对多维数组按指定键(如 name)分组,并将同组的 value 值以逗号连接后渲染为定义列表(<dl>),适用于 smarty 3+ 版本。
在实际开发中,我们常遇到后端传入的是扁平化结构的数组(如多个相同属性名对应不同值),但前端需要按属性归类展示——例如将多个 Paper 类型的规格 A4、A5 合并显示为 A4, A5。由于限制无法改动 PHP 层数据结构,必须纯模板内解决,Smarty 提供了简洁高效的原生方案。
核心思路分为两步:先构建分组映射数组,再遍历该映射生成目标 HTML。Smarty 支持在模板中动态创建和操作变量(包括多维数组),配合 implode 修饰器即可完成拼接。
✅ 正确实现步骤
-
第一步:构建分组关联数组
使用 {foreach} 遍历原始 $products,以 name 为键,将所有 value 推入对应子数组:
{foreach from=$products item=feature}
{$grouped[$feature.name][] = $feature.value}
{/foreach}⚠️ 注意:此语法依赖 Smarty 的「赋值表达式」特性(Smarty 3.1.22+ 默认启用)。若使用较老版本,需确认已开启 Smarty::setConfig('allow_php_tag', true) 或升级 Smarty。
-
第二步:遍历分组数组并渲染 <dl>
利用 key 获取分组名(即 name),item 获取该组所有 value 数组,再用 implode 修饰器以 ", " 连接:
<dl>
{foreach from=$grouped key=$name item=$values}
<dt>{$name}</dt>
<dd>{", "|implode:$values}</dd>
{/foreach}
</dl>最终输出即为符合预期的语义化 HTML:
<dl>
<dt>Fabric</dt>
<dd>Silk</dd>
<dt>Paper</dt>
<dd>A4, A5</dd>
</dl>? 补充说明与最佳实践
- 空值安全:若某 name 对应空 value 数组(如 []),{", "|implode:$values} 会安全输出空字符串,无需额外判断。
- 顺序保持:Smarty 的 foreach 遍历 $grouped 时,键的插入顺序即为首次出现顺序(PHP 7.4+ 关联数组保持插入序),因此 Fabric 会始终排在 Paper 前,与原始数组一致。
- 性能提示:该方案为单次遍历构建 + 单次遍历渲染,时间复杂度 O(n),适用于数百条以内的数据;超大规模建议移交 PHP 层预处理。
- 替代写法(兼容性更强):若环境禁用赋值表达式,可改用 {assign} 结合 unshift/push 模拟,但代码冗长且低效,不推荐。
掌握这一模式后,你还能轻松扩展至其他场景:如按 category 分组统计数量、按 status 聚合标签云等——本质都是「模板内数据重塑」,是提升 Smarty 模板表现力的关键技巧。

















