
本文介绍如何将 woocommerce 订单中多个商品的交货日期进行归并,把拥有相同日期的商品 id 合并到同一组,并保留独有日期独立成项,最终生成结构清晰、可直接用于前端展示的聚合数组。
本文介绍如何将 woocommerce 订单中多个商品的交货日期进行归并,把拥有相同日期的商品 id 合并到同一组,并保留独有日期独立成项,最终生成结构清晰、可直接用于前端展示的聚合数组。
在处理 WooCommerce 订单商品的自定义元字段(如 'Daty dostaw')时,常需对分散在不同商品中的交货日期做逻辑聚合:若多个商品共享某一天(如 25-08-2022),则应将其 product_id 合并为数组;而各自独有的日期则保持原结构不变。原始代码按商品遍历生成了以商品为单位的二维数组,但目标是「以日期为维度」重组数据。
下面提供一个健壮、可读性强且已验证可用的解决方案:
✅ 正确实现思路(两阶段处理)
第一阶段:建立日期索引映射
遍历所有商品及其日期列表,统计每个日期对应哪些商品 ID 和原始数组键($counter),便于后续归并与清理。第二阶段:构建新数组并清理冗余项
对每个出现 ≥2 次的日期,新建一项,product_id为 ID 数组,data为单元素日期字符串;同时从原数组中移除该日期,若某商品所有日期均被归并,则整项删除。
? 完整可运行代码示例
$order = wc_get_order(988613);
// Step 1: 构建原始 $daty 数组(与原文一致)
$daty = [];
$counter = 1;
foreach ($order->get_items() as $item_key => $item) {
$daty_dostaw = $item->get_meta('Daty dostaw');
$product_id = $item->get_product_id();
$dates = array_map('trim', explode(',', $daty_dostaw)); // 去除空格,更健壮
$daty[$counter] = [
'product_id' => $product_id,
'data' => $dates
];
$counter++;
}
// Step 2: 按日期归并(核心逻辑)
$dateMap = []; // key: 日期字符串 → value: ['ids' => [...], 'keys' => [...]]
foreach ($daty as $key => $item) {
foreach ($item['data'] as $date) {
if (!isset($dateMap[$date])) {
$dateMap[$date] = ['ids' => [], 'keys' => []];
}
$dateMap[$date]['ids'][] = $item['product_id'];
$dateMap[$date]['keys'][] = $key;
}
}
// Step 3: 构造结果数组 & 清理原数组
$result = [];
$nextIndex = 1;
// 先收集所有「被归并的日期」——即出现次数 ≥2 的日期
$mergedDates = array_filter($dateMap, fn($v) => count($v['ids']) > 1);
foreach ($mergedDates as $date => $entry) {
// 新增合并项:product_id 是去重后的数组,data 是单日期
$result[$nextIndex++] = [
'product_id' => array_values(array_unique($entry['ids'])),
'data' => [$date]
];
// 从原 $daty 中移除该日期(在对应 keys 的 data 中 unset)
foreach ($entry['keys'] as $origKey) {
if (isset($daty[$origKey]['data'])) {
$idx = array_search($date, $daty[$origKey]['data']);
if ($idx !== false) {
unset($daty[$origKey]['data'][$idx]);
// 若 data 为空,后续统一清理
$daty[$origKey]['data'] = array_values($daty[$origKey]['data']);
}
}
}
}
// Step 4: 追加剩余未被归并的项(product_id 单值 + 剩余 dates)
foreach ($daty as $key => $item) {
if (!empty($item['data'])) {
$result[$nextIndex++] = [
'product_id' => $item['product_id'],
'data' => $item['data']
];
}
}
// ✅ 最终结果存于 $result,结构完全符合预期
print_r($result);
⚠️ 注意事项与最佳实践
-
日期格式一致性:确保
'Daty dostaw'中所有日期格式统一(如dd-mm-yyyy),否则25-08-2022与25/08/2022将被视为不同日期。 -
去重处理:使用
array_unique()防止同一商品因配置错误重复添加相同日期。 -
键重排:
array_values()确保data子数组索引连续,避免 JSON 序列化时产生关联数组歧义。 -
性能提示:对于超大订单(>100 商品),建议改用
SplObjectStorage或预建哈希表优化,但常规场景无需过度优化。
✅ 总结
该方案不依赖第三方库,纯原生 PHP 实现,逻辑清晰、容错性强,完美达成「同日期聚合、异日期分离」的核心需求。你可直接集成至 WooCommerce 钩子(如 woocommerce_order_details_after_order_table)中,用于定制化交货日历或物流看板展示。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











