
本文介绍如何将每个玩具对象中多个货币价格字段(如 price_in_dollar、price_in_euro 等)扁平化为独立的多条记录,每条记录包含 toy、toy_id、rate 和 slug 四个字段,适用于报表生成、数据库归一化或 api 数据标准化场景。
本文介绍如何将每个玩具对象中多个货币价格字段(如 price_in_dollar、price_in_euro 等)扁平化为独立的多条记录,每条记录包含 toy、toy_id、rate 和 slug 四个字段,适用于报表生成、数据库归一化或 api 数据标准化场景。
在实际开发中,我们常遇到“宽表转长表”的需求:原始数据以对象形式存储,每个对象包含多个同类语义字段(如不同币种的价格),但下游系统或可视化工具需要每种价格单独成行。上述问题正是典型场景——需将每个玩具的四种价格字段(dollar/euro/pound/rupee)分别拆解为四条结构统一的新记录。
核心思路是:外层遍历原始数组,内层遍历每个对象的键值对,跳过标识性字段(toy_id、toy_name),对每个价格字段生成一条新记录,并复用固定字段。
以下是推荐的 PHP 实现代码:
$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_id', 'toy_name'], true)) {
continue; // 跳过基础字段
}
// 构建新行:复用 base + 动态 price 字段
$cars[] = array_merge($base, [
'rate' => $value,
'slug' => $key
]);
}
}
✅ 优势说明:
- 使用 array_merge() 显式组合基础字段与动态字段,逻辑清晰、不易出错;
- in_array(..., true) 启用严格类型检查,避免键名误匹配;
- 每次循环通过 $cars[] = ... 追加新元素,彻底解决原代码中因重复赋值导致仅保留最后一组数据的问题。
⚠️ 注意事项:
- 确保原始数据中所有价格字段均为数值类型,否则 rate 可能出现类型异常;
- 若后续新增价格字段(如 price_in_yen),该逻辑可自动兼容,无需修改代码;
- 如需按特定顺序输出(如 dollar → euro → pound → rupee),建议显式定义字段白名单而非依赖 foreach 遍历顺序。
最终输出的 $cars 数组即为符合要求的扁平化结构:共 2 个玩具 × 4 种货币 = 8 条记录,每条均含 toy、toy_id、rate 和 slug 四个键,语义明确、易于扩展、便于序列化或存入关系型数据库。










