news 2026/8/27 5:30:57

BoxPacker快速上手:用PHP算出每件商品进哪个箱子的装箱方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
BoxPacker快速上手:用PHP算出每件商品进哪个箱子的装箱方案

BoxPacker快速上手:用PHP算出每件商品进哪个箱子的装箱方案

【免费下载链接】BoxPacker4D bin packing / knapsack problem solver项目地址: https://gitcode.com/gh_mirrors/bo/BoxPacker

当仓库堆着上百件待发货商品、你还要手工试纸箱组合时,装箱就成了最费经验的事。BoxPacker 是一个 PHP 的 4D 装箱求解库,输入商品与纸箱的尺寸重量,直接给出每件商品进哪个箱的方案。上百件商品通常在秒级算完,接入只需实现两个接口。

它能帮你做什么

计算每件商品的落箱方案

它的主循环很简单:开一个箱子、尽量装满、再开下一个,直到所有商品放完。入口在 src/Packer.php。

  • 返回 PackedBoxList,每个箱子带出装了哪些商品、各自的 x/y/z 坐标
  • 同时登记多种纸箱,自动先尝试装得下全部剩余商品的箱子
  • 某个商品装不下时,可选择抛异常或把剩余商品留给你处理

平衡多箱之间的重量

装完不是终点。多箱时 src/WeightRedistributor.php 会做第二轮重分配。

  • 在箱子之间挪动商品,避免一箱很沉、一箱很轻
  • 默认只在箱子数不超过 12 时执行,再多就跳过以节省计算时间
  • 重分配时会同时校验每个箱子的最大承重

按业务规则约束摆放

不是所有商品都能任意放。约束通过接口实现,见 src/ConstrainedPlacementItem.php。

  • 用 src/Rotation.php 的三个值控制朝向:固定方向、可横转 90 度、任意方向
  • 实现 canBePacked() 就能表达"每箱最多几节电池"这类规则
  • 用 LimitedSupplyBox 声明某规格纸箱的有限库存

从零到跑通

  1. 获取代码:git clone https://gitcode.com/gh_mirrors/bo/BoxPacker,或直接作为依赖composer require dvdoug/boxpacker
  2. 安装依赖:项目目录执行composer install,要求 PHP 8.2 及以上
  3. 跑最小示例:下面 12 行代码完成加箱、加商品、求方案、读结果
use DVDoug\BoxPacker\Packer; use DVDoug\BoxPacker\Rotation; use DVDoug\BoxPacker\Test\TestBox; use DVDoug\BoxPacker\Test\TestItem; $packer = new Packer(); $packer->addBox(new TestBox(reference: '小箱', outerWidth: 300, outerLength: 200, outerDepth: 150, emptyWeight: 30, innerWidth: 296, innerLength: 196, innerDepth: 146, maxWeight: 10000)); $packer->addItem(new TestItem(description: '商品A', width: 100, length: 80, depth: 60, weight: 200, allowedRotation: Rotation::BestFit), qty: 3); $packedBoxes = $packer->pack(); echo $packedBoxes->count(), ' 个箱子被打开';

跑通后你应该看到:控制台打印"1 个箱子被打开",说明 3 件商品全部装进了小箱。

想要更完整的输入格式,看 tests/ 里的现成实现和 docs/getting-started.rst,不必贴测试代码,照着改就行。

深入用法与关键配置

如何给装箱计算设置超时

适用场景:商品多或纸箱种类多时,计算时间不可控,不能让请求无限等下去。

use DVDoug\BoxPacker\DefaultTimeoutChecker; $packer->setTimeoutChecker(new DefaultTimeoutChecker(timeout: 5.0)); // 单位:秒

预期效果:任何一步检查发现超过 5 秒就抛出 TimeoutException,你可以捕获后走降级逻辑,而不是干等。

如何处理塞不进去的商品

适用场景:某件商品比所有纸箱都大,默认行为是抛 NoBoxesAvailableException 中断整个计算。

一行改动:$packer->throwOnUnpackableItem(false)

预期效果:pack() 正常返回已装好的箱子,没塞进的商品留在 src/Packer.php 的 getUnpackedItems() 里,交给人工或二次装箱。

如何限制商品摆放方向

适用场景:易碎、带"此面向上"标识的商品不能侧放。

在 Item 实现的 getAllowedRotation() 里返回值即可:Rotation::Never只允许定义方向,Rotation::KeepFlat可横转 90 度,Rotation::BestFit任意朝向。

预期效果:侧放方案从搜索结果中直接排除,不会出现在最终箱子里。

它适合谁

电商订单发货

订单确认后,你需要马上知道用几个箱、什么规格。

  • 下单时直接算出纸箱规格与数量,替代人工估箱
  • 箱子实际重量可直接对接承运商 API,运费预估与实际偏差更小
  • 打印的运单数等于返回的箱子数,不缺单也不浪费

仓库出库复核

仓管按方案装箱,复核靠清单核对。

  • 每个商品带 x/y/z 坐标,打印出库清单后与实物逐项对照
  • 多箱时重量自动再平衡,避免一箱沉一箱轻,托盘码放更稳
  • 方案与实物对不上时重跑一次即可,不用手工重排

物流报价与批量规划

批量询价要快速给出箱数和成本。

  • 输入商品清单即得总箱数,报价不靠手工试错
  • LimitedSupplyBox 声明纸箱库存,方案不会推荐你没有的箱
  • 需要对比方案时,packAllPermutations() 能列出全部箱型组合,箱型多时较慢,慎用

内部怎么运作

  • Packer:src/Packer.php — 主入口,逐箱试装直到全部放完,最后触发重量平衡
  • VolumePacker:src/VolumePacker.php — 负责单箱内部的摆放,逐件落位
  • WorkingVolume:src/WorkingVolume.php — 记录箱内剩余可用空间,每放一件更新一次
  • OrientatedItemFactory:src/OrientatedItemFactory.php — 按允许朝向展开商品的所有合法摆法并排序
  • WeightRedistributor:src/WeightRedistributor.php — 全部装完后跨箱挪动商品、均衡重量
  • DefaultTimeoutChecker:src/DefaultTimeoutChecker.php — 每步检查耗时,超限抛 TimeoutException

数据流就一条线:商品和箱子进入 Packer,分发给 VolumePacker 逐箱填充,WorkingVolume 保证每次落位不重叠,最后 WeightRedistributor 匀一遍重量,以 PackedBoxList 交还给你。

上生产前注意什么

  • 当商品数量上千或箱型超过十几种时,建议先挂上 TimeoutChecker,用真实订单数据压测一遍再定阈值
  • 当有商品装不进任何箱子时,默认抛 NoBoxesAvailableException;想降级就throwOnUnpackableItem(false),再从 getUnpackedItems() 取回剩余商品
  • 当箱子数超过 12(maxBoxesToBalanceWeight 默认值)时,重量平衡会被跳过,需要时调高该值
  • 当箱型较多时,不要在生产路径调用 packAllPermutations(),组合数量会随箱型数膨胀

参与与支持

  • Issues 入口:功能建议与缺陷直接提交到仓库 Issues,附上最小复现的商品与箱子尺寸
  • 完整文档:本地 docs/ 目录覆盖从安装到约束摆放的全部主题,这篇示例的展开版在 docs/getting-started.rst
  • 示例代码:tests/ 里有可直接借鉴的 Box 与 Item 实现,以及公开测试用例的回归数据

写在最后

手工试纸箱组合这件事,可以交给代码了。花 5 分钟:装好依赖,把上面 12 行示例跑一遍,再用你自己业务的对象替换 TestBox 和 TestItem。当 pack() 返回的每个箱子都能说清装了什么、多重、放在哪个坐标,它就算正式上岗。MIT 协议的开源项目,接入成本就是实现两个接口。

【免费下载链接】BoxPacker4D bin packing / knapsack problem solver项目地址: https://gitcode.com/gh_mirrors/bo/BoxPacker

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/27 5:30:40

DFS三大高阶应用场景:博弈树、连通极值与约束满足

1. 这三道题为什么被放在一起讲?——DFS在博弈、图论与路径约束中的统一内核你点开这标题,大概率是刚刷完蓝桥杯真题集,或者被“Guarding the Farm S”这道USACO老题卡在了WA上,又或者正对着“挖地雷”这道经典回溯题反复调试却总…

作者头像 李华
网站建设 2026/8/27 5:30:37

流行音乐发展史的量化建模方法论

1. 项目本质与真实价值定位“2013年认证杯SPSSPRO杯数学建模B题(第一阶段)流行音乐发展简史全过程文档及程序”——这个标题乍看像一份陈年竞赛资料打包,但拆开来看,它其实是一份被严重低估的跨学科方法论标本。我带过七届数学建模…

作者头像 李华
网站建设 2026/8/27 5:30:07

基于YOLOv8的甲骨文字符检测识别系统构建与优化实践

1. 项目概述与背景最近在整理一些历史资料时,发现了一个挺有意思的挑战:如何让计算机“看懂”甲骨文。这可不是简单的文字识别,而是要从一堆斑驳、模糊、甚至残缺的龟甲兽骨拓片或照片里,把那些古老的字符一个个精准地定位并识别出…

作者头像 李华
网站建设 2026/8/27 5:30:05

YOLOv8实时手语识别实战:从数据标注到部署的完整方案

简介:目标检测是计算机视觉中的基础任务,其核心在于同时定位目标位置与类别。YOLOv8作为高性能检测模型,凭借实时性与精度平衡,成为手势识别等动态视觉任务的理想选择。在实际工程中,手语识别的难点常不在于模型结构&a…

作者头像 李华
网站建设 2026/8/27 5:24:23

基于Simulink的LSTM、GRU、ARIMAX时间序列预测实战

简介:时间序列预测是工业控制、电力调度、自动驾驶等领域的关键技术,核心在于从历史数据中挖掘时序规律。常用的预测模型包括统计模型ARIMAX与深度模型LSTM、GRU:ARIMAX擅长捕捉线性趋势和外生变量影响,LSTM通过门控机制建模长程依…

作者头像 李华
网站建设 2026/8/27 5:24:15

C#部署YOLOv11-OBB旋转框检测:ONNX模型集成与工程实践

简介:目标检测是计算机视觉的核心任务之一,旨在定位和识别图像中的物体。传统水平矩形框(AABB)在处理倾斜物体时,会引入大量背景噪声,影响后续分析的精度。旋转框检测(OBB)技术通过引…

作者头像 李华