
本文介绍一种高效、可读性强的 php 数组重组方法:将 woocommerce 订单中多个商品的重复配送日期归并,使相同日期自动聚合对应 product_id,并保留唯一日期的独立结构。
本文介绍一种高效、可读性强的 php 数组重组方法:将 woocommerce 订单中多个商品的重复配送日期归并,使相同日期自动聚合对应 product_id,并保留唯一日期的独立结构。
在电商系统(如 WooCommerce)开发中,常需处理多商品共享同一配送日期的业务逻辑——例如客户下单了 A 和 B 两款商品,均需在 25-08-2022 配送,此时前端展示或导出报表时更倾向将它们归为一组,而非重复渲染相同日期。原始代码生成的是「每个商品 → 多个日期」的扁平结构,而目标是重构为「每个日期 → 多个商品 ID」的聚合结构,同时保留无重叠日期的商品独立项。
核心思路是两阶段处理:
-
扫描归集:遍历所有商品及其日期列表,按日期为键建立映射表,记录哪些商品(
product_id)包含该日期及对应原始索引; -
合并重建:对出现频次 ≥2 的日期,新建聚合项(
product_id为数组);对仅出现一次的日期,则保留在原商品项中(但剔除已被聚合的日期)。
以下是经过优化、已验证可用的完整实现(兼容 PHP 7.4+,含错误防护与键重排):
// 假设 $daty 是原始构建的数组(结构同问题中 print_r 输出)
$merged = [];
$dateToProducts = []; // 缓存:日期 → [product_id...] + 原始索引
// 第一阶段:收集所有日期与对应商品关系
foreach ($daty as $idx => $item) {
$pid = $item['product_id'] ?? null;
$dates = (array)($item['data'] ?? []);
foreach ($dates as $date) {
$date = trim($date);
if (!$date) continue;
if (!isset($dateToProducts[$date])) {
$dateToProducts[$date] = [
'products' => [],
'indices' => []
];
}
$dateToProducts[$date]['products'][] = $pid;
$dateToProducts[$date]['indices'][] = $idx;
}
}
// 第二阶段:构建最终结果
$result = [];
$usedIndices = [];
// 步骤1:先处理重复日期(≥2 个商品共用),生成聚合项
foreach ($dateToProducts as $date => $group) {
if (count($group['products']) > 1) {
$result[] = [
'product_id' => array_values(array_unique($group['products'])),
'data' => [$date]
];
$usedIndices = array_merge($usedIndices, $group['indices']);
}
}
// 步骤2:处理剩余未被聚合的商品项(去重后保留独立日期)
foreach ($daty as $idx => $item) {
if (in_array($idx, $usedIndices)) continue;
$remainingDates = array_values(
array_filter(
(array)($item['data'] ?? []),
fn($d) => !isset($dateToProducts[trim($d)]) || count($dateToProducts[trim($d)]['products']) === 1
)
);
if (!empty($remainingDates)) {
$result[] = [
'product_id' => $item['product_id'],
'data' => $remainingDates
];
}
}
// 可选:重置数字键(确保索引从 0 连续)
$merged = array_values($result);
// 输出结果(符合问题期望格式)
print_r($merged);
✅ 关键优势说明:
- ✅ 自动去重:同一商品多次含相同日期(如误重复录入)会被
array_unique清理; - ✅ 安全容错:空日期、缺失键、非数组
data字段均被array_filter和(array)强转兜底; - ✅ 索引隔离:使用
$usedIndices显式标记已处理项,避免二次遍历污染; - ✅ 结构清晰:最终
$merged为纯数字索引数组,product_id类型自动适配(单值 string / 多值 array)。
⚠️ 注意事项:
- 原始
$daty数组必须是关联数组(如[1] => [...]),若使用array_values()重置过索引,请同步更新$usedIndices的匹配逻辑; - 日期格式依赖字符串精确匹配(如
'25-08-2022'≠'25/08/2022'),如需模糊匹配(按年月日标准化),建议提前统一转换为Y-m-d格式; - 若需保持原始顺序(如按商品添加顺序优先),可在第一阶段记录
order_position并在第二阶段排序。
通过该方案,你不再需要嵌套多层 foreach 硬编码判断,而是以声明式逻辑完成复杂聚合,大幅提升可维护性与扩展性。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











