You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

按20kg/箱拆分产品数组并计算对应总容积的PHP实现问题

PHP 产品装箱逻辑修正:按20kg阈值装箱并计算总容积

看起来你的现有代码在处理装箱逻辑时出现了不少问题,比如重复添加产品、容积计算混乱、剩余产品处理逻辑错误,导致无法得到你预期的装箱结果。我帮你重新梳理了逻辑,写出了符合需求的修正代码,同时会解释关键的实现点。

需求回顾

我们需要把产品按每箱最大20kg的规则装箱,同时计算每个箱子的总容积,核心逻辑是:

  • 优先整组装入产品,若整组装入后超过阈值,则拆分该组,取部分产品填满当前箱子,剩余部分放入下一箱
  • 示例(第一箱):装入第一组(6.5kg)、第二组(9kg),再从第三组取3个(4.5kg),总重刚好20kg,总容积按实际装入的产品数量对应计算

现有代码的问题

  1. 重复将同一产品添加到箱子中($boxes[$box_number][] = $product;执行了两次)
  2. 容积计算逻辑混乱,变量ttal_cub、the_cubic的处理没有对应实际装箱的产品数量
  3. 剩余产品的处理逻辑错误,没有正确延续到下一个箱子继续填充
  4. 箱子的重量累加逻辑不符合“先整组装,装不下拆组”的需求

修正后的代码

<?php
// 定义每箱最大重量阈值
$BOX_WEIGHT_LIMIT = 20;
$itemArray = [];

foreach ($main as $key => $products) {
    $boxes = [];
    $currentBoxIndex = 0;
    // 初始化第一个箱子,包含总重、总容积、箱内产品明细
    $boxes[$currentBoxIndex] = [
        'total_weight' => 0,
        'total_cubic' => 0,
        'items' => []
    ];

    foreach ($products as $product) {
        // 复制产品数据,避免修改原数组的原始值
        $remainingProduct = $product;

        // 循环处理当前产品的剩余数量,直到全部装箱完成
        while ($remainingProduct['quantity'] > 0) {
            $currentBox = &$boxes[$currentBoxIndex];
            // 计算当前箱子还能容纳的重量
            $remainingWeight = $BOX_WEIGHT_LIMIT - $currentBox['total_weight'];

            if ($remainingWeight <= 0) {
                // 当前箱子已满,创建新箱子并切换过去
                $currentBoxIndex++;
                $boxes[$currentBoxIndex] = [
                    'total_weight' => 0,
                    'total_cubic' => 0,
                    'items' => []
                ];
                continue;
            }

            // 计算当前箱子最多能装该产品的数量
            $maxPossibleQty = floor($remainingWeight / $remainingProduct['weight']);
            if ($maxPossibleQty <= 0) {
                // 单个产品重量超过箱子剩余容量,这里假设业务中不会出现这种情况,如需处理可在此添加逻辑
                break;
            }

            // 实际取的数量:不超过产品剩余数量,也不超过箱子可装数量
            $takeQty = min($maxPossibleQty, $remainingProduct['quantity']);
            $takeWeight = $takeQty * $remainingProduct['weight'];
            
            // 计算对应容积:两种方式可选,根据你的实际数据结构调整
            // 方式1:按单个产品容积计算(适合cubic是单个产品的容积)
            $takeCubic = $takeQty * $remainingProduct['cubic'];
            // 方式2:按总容积比例计算(适合total_cubic是该组产品的总容积)
            // $takeCubic = $remainingProduct['total_cubic'] * ($takeQty / $remainingProduct['quantity']);

            // 将取出的产品部分加入当前箱子
            $currentBox['items'][] = [
                'product_id' => $remainingProduct['product_id'],
                'quantity' => $takeQty,
                'weight' => $remainingProduct['weight'],
                'cubic' => $remainingProduct['cubic'],
                'total_weight' => $takeWeight,
                'total_cubic' => $takeCubic
            ];
            // 更新当前箱子的总重量和总容积
            $currentBox['total_weight'] += $takeWeight;
            $currentBox['total_cubic'] += $takeCubic;

            // 更新剩余产品的数量和总重量
            $remainingProduct['quantity'] -= $takeQty;
            $remainingProduct['total_weight'] -= $takeWeight;

            if ($remainingProduct['quantity'] == 0) {
                // 当前产品已全部装箱,跳出循环处理下一个产品
                break;
            } else {
                // 当前箱子已满,创建新箱子继续装剩余产品
                $currentBoxIndex++;
                $boxes[$currentBoxIndex] = [
                    'total_weight' => 0,
                    'total_cubic' => 0,
                    'items' => []
                ];
            }
        }
    }

    // 整理输出格式,匹配你原代码的输出结构(可根据实际需求调整)
    $formattedBoxes = [];
    foreach ($boxes as $boxIdx => $box) {
        $formattedBoxes[] = [
            'item_reference' => $products[0]['order_id'],
            'cubic_volume' => number_format($box['total_cubic'], 5),
            'weight' => number_format($box['total_weight'], 2),
            'packaging_type' => 'CTN',
            'product_id' => 'EXP',
            'authority_to_leave' => false, // 原代码中$orders未定义,这里默认false,可根据实际情况修改
            'tracking_details' => [
                'article_id' => 'test',
                'consignment_id' => 'test',
                'barcode_id' => 'test'
            ],
            'items' => $box['items'] // 可选:保留箱内产品明细,方便核对
        ];
    }

    $itemArray[] = $formattedBoxes;
}

echo "<pre>";
print_r($itemArray);
echo "</pre>";
?>

关键逻辑说明

  1. 箱子生命周期管理:每个订单开始时初始化第一个箱子,当当前箱子剩余容量不足时自动创建新箱子,确保装箱流程连续。
  2. 逐产品循环处理:对每个产品,循环处理其剩余数量,直到该产品全部装入箱子,避免遗漏。
  3. 精准计算可装数量:根据箱子剩余重量和产品单重,计算最多能装的产品数量,确保不超过重量阈值。
  4. 容积计算适配:提供两种容积计算方式,你可以根据实际数据结构(cubic是单个产品容积还是组总容积)切换使用。
  5. 剩余产品延续处理:如果产品未全部装完,自动切换到新箱子继续处理,保证产品不会被丢弃。

验证示例

针对你给出的第一箱需求:

  • 第一组产品(5个,6.5kg)全部装入,容积按方式1计算为5*0.00267=0.01335(如果用方式2则是原total_cubic0.00267)
  • 第二组产品(6个,9kg)全部装入,容积为6*0.00348=0.02088(方式2则是0.00348)
  • 第三组产品取3个(4.5kg),容积为3*0.00267=0.00801(方式2则是0.00267*(3/7)=0.00114)
  • 总重6.5+9+4.5=20kg,符合阈值要求

你可以根据自己的实际数据结构调整容积计算方式,确保得到你预期的结果。

内容的提问来源于stack exchange,提问作者David

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:16:31