
本文介绍如何将每个玩具对象中多个货币价格字段(如 price_in_dollar、price_in_euro 等)拆分为独立的数据行,生成统一格式的扁平化数组,便于后续展示、导出或分析。
本文介绍如何将每个玩具对象中多个货币价格字段(如 price_in_dollar、price_in_euro 等)拆分为独立的数据行,生成统一格式的扁平化数组,便于后续展示、导出或分析。
在实际开发中,我们常遇到“宽表转长表”的需求:原始数据以对象形式存储,每个对象包含多个同类型字段(如不同币种的价格),但业务逻辑或前端渲染更期望每条记录只描述一个维度(例如一条记录代表“Truck 在美元下的价格”)。这种结构转换也称为数据“归一化”或“行展开(row distribution)”。
要实现该目标,核心思路是:对每个原始玩具对象,遍历其所有键值对,识别出需保留的公共字段(toy_id、toy_name),再将其余价格字段逐个提取为新行,并映射为 rate 和 slug 字段。
以下是推荐的 PHP 实现方案(兼容 PHP 7.4+):
$cars = [];
foreach ($data as $r) {
// 提取不变的公共信息
$base = [
'toy' => $r['toy_name'],
'toy_id' => $r['toy_id']
];
// 遍历所有字段,跳过已提取的公共字段
foreach ($r as $key => $value) {
if (in_array($key, ['toy_name', 'toy_id'], true)) {
continue;
}
// 构造新行:保留 base 信息 + 当前价格字段的值与键名
$cars[] = array_merge($base, [
'rate' => $value,
'slug' => $key
]);
}
}✅ 优势说明:
- 使用 array_merge() 确保每次生成全新数组,避免引用污染;
- in_array(..., true) 启用严格比较,防止键名误匹配;
- 逻辑清晰分离“基础字段”与“动态字段”,易于扩展(如新增 price_in_yen 无需修改逻辑)。
⚠️ 注意事项:
- 原始数据中所有价格字段必须为标量值(int/float),若存在 null 或嵌套结构,需提前校验;
- 若需按特定顺序输出(如 dollar → euro → pound → rupee),建议显式定义货币键名数组并遍历,而非依赖 foreach 的内部顺序(PHP 8+ 中关联数组遍历顺序已稳定,但仍建议显式控制以增强可维护性);
- 大数据量场景下(如 >10,000 条原始记录),可考虑使用生成器(Generator)流式处理,避免内存溢出。
最终输出结果将严格符合预期结构:每个玩具生成 N 条记录(N = 价格字段数),每条记录含 toy、toy_id、rate 和 slug 四个标准键,真正实现数据形态的规范化与可扩展性。

















