PHPackages                             daika7ana/smallest-box - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. daika7ana/smallest-box

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

daika7ana/smallest-box
======================

Calculate the smallest rectangular box (W x L x H) that fits a set of rectangular items, using axis-aligned 3D bin packing with rotation support.

1.1.0(2w ago)011GPL-3.0-or-laterPHPPHP &gt;=7.4CI passing

Since May 30Pushed 2w agoCompare

[ Source](https://github.com/daika7ana/smallest-box)[ Packagist](https://packagist.org/packages/daika7ana/smallest-box)[ RSS](/packages/daika7ana-smallest-box/feed)WikiDiscussions master Synced 1w ago

READMEChangelog (2)Dependencies (6)Versions (4)Used By (0)

smallest-box
============

[](#smallest-box)

[![CI](https://github.com/daika7ana/smallest-box/actions/workflows/ci.yml/badge.svg)](https://github.com/daika7ana/smallest-box/actions/workflows/ci.yml)[![PHP 7.4+](https://camo.githubusercontent.com/8585e47165388f80f6740d3bf5ff08aaca1d9159c0458375cc0377dca9eedfe8/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d372e342532422d3737374242343f7374796c653d666c61742d737175617265266c6f676f3d706870)](https://www.php.net/)[![PHPUnit](https://camo.githubusercontent.com/f58aef4c4d697218bd5252a42b3870c26fe9f5531946c8a9d7064a29100d800f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f504850556e69742d392e782d3041374242423f7374796c653d666c61742d737175617265)](docs/testing.md)[![PHPStan](https://camo.githubusercontent.com/34f0f743d0d6fb102bb6d17f199e1a55bcbe23d82743e136482983e8905d8441/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d4c6576656c253230382d626c75653f7374796c653d666c61742d737175617265)](phpstan.neon)[![License](https://camo.githubusercontent.com/2be05c1ee647f7bcb4f547df19cc78f192a840670c62767563f0e2b3b6e52c0c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d47504c2d2d332e302d2d6f722d2d6c617465722d677265656e3f7374796c653d666c61742d737175617265)](LICENSE)

Calculate the smallest rectangular box that fits a set of rectangular items, using axis-aligned 3D bin packing with rotation support.

> Zero dependencies, fully typed, three packing algorithms, and rotation-aware candidate generation.

Table of Contents
-----------------

[](#table-of-contents)

- [Features](#features)
- [Requirements](#requirements)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Packing Algorithms](#packing-algorithms)
- [Custom Sort &amp; Pack Orders](#custom-sort--pack-orders)
- [Testing](#testing)
- [Documentation](#documentation)

Features
--------

[](#features)

### Core Strengths

[](#core-strengths)

- ✅ **Smallest Box Finding** — Greedy 3D bin packing with rotation support
- ✅ **Six Axis-Aligned Rotations** — Items tested in all orientations for optimal fit
- ✅ **Three Packing Algorithms** — Guillotine, MaxRects, and ExtremePoint
- ✅ **Custom Sort &amp; Pack Orders** — Fine-tune item ordering via closures
- ✅ **Fluent API** — Build item lists incrementally with `add()`, `remove()`, `clear()`
- ✅ **Immutable Value Objects** — `Item` and `Box` with type-safe accessors
- ✅ **Static Analysis with PHPStan** — Strict type checks across the codebase
- ✅ **Zero Dependencies** — Only requires PHP 7.4+

### Perfect For

[](#perfect-for)

- 🎯 Logistics and shipping box optimisation
- 🎯 Warehouse packing calculations
- 🎯 3D layout and spatial planning
- 🎯 Any scenario needing the smallest bounding box for rectangular items

Requirements
------------

[](#requirements)

- **PHP 7.4+**

Installation
------------

[](#installation)

### Via Composer

[](#via-composer)

```
composer require daika7ana/smallest-box
```

Quick Start
-----------

[](#quick-start)

### Pass items directly

[](#pass-items-directly)

```
use Daika7ana\SmallestBox\Item;
use Daika7ana\SmallestBox\SmallestBoxFinder;

$items = [
    new Item(5.0, 3.0, 2.0),
    new Item(3.0, 3.0, 3.0),
    new Item(2.0, 2.0, 1.0),
];

$finder = new SmallestBoxFinder();
$box = $finder->find($items);

echo $box;           // "5.00 x 5.00 x 3.00"
echo $box->volume(); // 75.0
```

### Build item list incrementally

[](#build-item-list-incrementally)

```
$finder = new SmallestBoxFinder();

$finder
    ->add(new Item(5.0, 3.0, 2.0))
    ->add(new Item(3.0, 3.0, 3.0))
    ->add(new Item(2.0, 2.0, 1.0));

$box = $finder->find();
```

### Choose a packing algorithm

[](#choose-a-packing-algorithm)

```
// Default: guillotine (fast, ~65% efficiency for diverse items)
$finder = new SmallestBoxFinder();

// MaxRects (slower, ~100% efficiency for diverse items)
$finder = new SmallestBoxFinder(SmallestBoxFinder::ALGO_MAXRECTS);

// ExtremePoint (medium speed, ~75% efficiency for diverse items)
$finder = new SmallestBoxFinder(SmallestBoxFinder::ALGO_EXTREMEPOINT);
```

That's it! You've got the smallest box that fits all your items.

Packing Algorithms
------------------

[](#packing-algorithms)

AlgorithmEfficiencySpeedBest For`ALGO_GUILLOTINE` (default)~65%FastUniform items, speed-critical`ALGO_EXTREMEPOINT`~75%MediumBalanced efficiency and speed`ALGO_MAXRECTS`~100%SlowerDiverse items, best fit### How It Works

[](#how-it-works)

1. **Sort** items by multiple heuristics (volume, dimensions, footprint).
2. **Generate** candidate box dimensions from item dimension permutations and sums.
3. **Test** each candidate with the selected packing algorithm and all six rotations.
4. **Return** the smallest box that successfully fits all items.

Custom Sort &amp; Pack Orders
-----------------------------

[](#custom-sort--pack-orders)

Fine-tune packing behaviour for your specific use case:

```
$finder = new SmallestBoxFinder();

// Sort items by height ascending (build layers from bottom up)
$finder->addSortOrder(function (Item $a, Item $b): int {
    return $a->height()  $b->height();
});

// Pack widest items first
$finder->addPackOrder(function (Item $a, Item $b): int {
    return $b->width()  $a->width();
});

$box = $finder->find($items);
```

Custom orders are tried after the built-in ones. Both methods support fluent chaining.

Testing
-------

[](#testing)

### Run Static Analysis

[](#run-static-analysis)

```
composer stan
```

PHPStan is configured via `phpstan.neon` and analyses the `src/` directory.

### Run Code Style Checks

[](#run-code-style-checks)

```
composer pint
```

### Run Full Test Suite

[](#run-full-test-suite)

```
composer test
```

### Run The Same Checks As CI

[](#run-the-same-checks-as-ci)

```
composer ci
```

Available Composer scripts:

- `composer pint` — Check code style (Laravel Pint)
- `composer stan` — Run static analysis (PHPStan)
- `composer test` — Run the test suite (PHPUnit)
- `composer ci` — Run all checks in sequence

Documentation
-------------

[](#documentation)

GuidePurpose📖 [Usage &amp; Examples](docs/usage.md)Working examples and patterns🔧 [Installation](docs/installation.md)Detailed setup instructions📋 [API Reference](docs/api-reference.md)Complete class and method reference⚙️ [Algorithm Details](docs/algorithm.md)How the packing algorithms work---

Made with ❤️

**Questions?** [Check the docs](docs/usage.md) or [open an issue](../../issues)

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance97

Actively maintained with recent releases

Popularity7

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity36

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~40 days

Total

2

Last Release

14d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/11703528?v=4)[Dan-Radu Pana](/maintainers/daika7ana)[@daika7ana](https://github.com/daika7ana)

---

Top Contributors

[![daika7ana](https://avatars.githubusercontent.com/u/11703528?v=4)](https://github.com/daika7ana "daika7ana (11 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/daika7ana-smallest-box/health.svg)

```
[![Health](https://phpackages.com/badges/daika7ana-smallest-box/health.svg)](https://phpackages.com/packages/daika7ana-smallest-box)
```

###  Alternatives

[php-mcp/schema

PHP Data Transfer Objects (DTOs) and Enums for the Model Context Protocol (MCP) schema.

19510.1k4](/packages/php-mcp-schema)[ibrahimbougaoua/filament-sort-order

This is my package filament-sort-order

2116.0k](/packages/ibrahimbougaoua-filament-sort-order)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
