PHPackages                             ronappleton/organisational-unit - 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. ronappleton/organisational-unit

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

ronappleton/organisational-unit
===============================

Pattern for managing organisational structures, from management structures, to company structures to any kind or organisational structure.

00PHPCI failing

Since Dec 9Pushed 3mo ago1 watchersCompare

[ Source](https://github.com/ronappleton/organisational-unit)[ Packagist](https://packagist.org/packages/ronappleton/organisational-unit)[ RSS](/packages/ronappleton-organisational-unit/feed)WikiDiscussions master Synced today

READMEChangelogDependenciesVersions (1)Used By (0)

[![Laravel](https://camo.githubusercontent.com/4a98123f3416c1e91b1616838d42e4bd5231f0a31c00b024a4d56168f22c1603/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c61726176656c2d2532334646324432302e7376673f7374796c653d666f722d7468652d6261646765266c6f676f3d6c61726176656c266c6f676f436f6c6f723d7768697465)](https://camo.githubusercontent.com/4a98123f3416c1e91b1616838d42e4bd5231f0a31c00b024a4d56168f22c1603/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c61726176656c2d2532334646324432302e7376673f7374796c653d666f722d7468652d6261646765266c6f676f3d6c61726176656c266c6f676f436f6c6f723d7768697465)[![Codacy Badge](https://camo.githubusercontent.com/6926cab594d918112508c5379b7a0330c462736199ca4507defe5ab09293c57c/68747470733a2f2f6170702e636f646163792e636f6d2f70726f6a6563742f62616467652f47726164652f3665303961633136343865663461303561666261626236643739383337336463)](https://app.codacy.com/gh/ronappleton/organisational-unit/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)[![Codacy Badge](https://camo.githubusercontent.com/abd0e36a0ea6ace5e6cc5bd6f09b4a56860b0814494696bed66504f571606ccb/68747470733a2f2f6170702e636f646163792e636f6d2f70726f6a6563742f62616467652f436f7665726167652f3665303961633136343865663461303561666261626236643739383337336463)](https://app.codacy.com/gh/ronappleton/organisational-unit/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage)

📦 Organisational Unit Backbone
==============================

[](#-organisational-unit-backbone)

A lightweight, high-performance hierarchical structure &amp; metadata system for Laravel applications.

This package provides a **generic organisational unit backbone**, designed as a universal building block for representing **anything hierarchical**:

- Schools → Year Groups → Classes
- Warehouses → Zones → Aisles → Racks → Bins
- Corporate Org Charts
- Facilities → Buildings → Floors → Rooms
- Taxonomies
- Asset Locations
- Multi-tenant logical structures

It provides:

- A **lean organisational\_units table** (bigint, indexed, fast)
- Optional **morph link to any model**
- Fully managed **parent/child tree structure**
- Typed, polymorphic **metadata**
- Clean, extensible **query builder helpers**
- PHP-side tree utilities (descendants, ancestors, etc.)
- Automatic cascading of soft deletes / restores

🚀 Why start your project with this backbone?
--------------------------------------------

[](#-why-start-your-project-with-this-backbone)

Most systems *accidentally* recreate these same problems:

- “We need a structure of buildings → rooms → sensors.”
- “We need departments → teams → roles.”
- “We need product categories.”
- “We need a place hierarchy.”
- “We need dynamic classifications.”
- “We need custom per-node metadata.”

Every time, developers start from scratch.

By beginning with this backbone you get:

- **Universal applicability**
- **Strong consistency**
- **Flexibility without performance loss**
- **Extensibility without schema rewrites**
- **Scalable metadata system**
- **Tree tools baked in**

This becomes a foundation your entire ecosystem can depend on.

📥 Installation
--------------

[](#-installation)

```
composer require appleton/organisational-unit
php artisan migrate
```

🗂️ Database Structure
---------------------

[](#️-database-structure)

The `organisational_units` table contains:

- id (bigint PK)
- parent\_id (nullable FK)
- entity\_type / entity\_id (nullable morph)
- name
- code
- type
- tenant\_id
- soft deletes + timestamps

Indexes exist on:

- parent\_id
- entity\_type, entity\_id
- type
- code
- tenant\_id
- tenant\_id, type

🌳 Model Usage
-------------

[](#-model-usage)

```
$unit = OrganisationalUnit::create([
    'name' => 'Warehouse A',
    'type' => 'warehouse',
]);
```

Parent / Children
-----------------

[](#parent--children)

```
$unit->parent;
$unit->children;
```

Linking Entities
----------------

[](#linking-entities)

```
$unit->entity()->associate($model)->save();
```

Moving Units
------------

[](#moving-units)

```
$unit->moveToParent($newParentId);
```

Building Trees
--------------

[](#building-trees)

```
$tree = OrganisationalUnit::buildTree();
```

Descendants / Ancestors
-----------------------

[](#descendants--ancestors)

```
$unit->descendants();
$unit->getParentChain();
```

🧠 Query Builder
---------------

[](#-query-builder)

```
OrganisationalUnit::query()
    ->root()
    ->tenant(5)
    ->ofType('bin')
    ->entityType(User::class)
    ->get();
```

🏷️ Metadata
-----------

[](#️-metadata)

Set metadata:

```
$unit->setMeta('capacity', 300);
$unit->setMeta('is_active', true);
$unit->setMeta('config', ['threshold' => 10]);
```

Get metadata:

```
$unit->getMeta('capacity');
```

Remove:

```
$unit->forgetMeta('capacity');
```

🏫 Example: School
-----------------

[](#-example-school)

```
$school = OU::create(['name' => 'Greenfields Primary', 'type' => 'school']);
$ks1 = OU::create(['name' => 'Key Stage 1', 'parent_id' => $school->id]);
$y1 = OU::create(['name' => 'Year 1', 'parent_id' => $ks1->id]);

$classA = OU::create([
    'name' => '1A',
    'parent_id' => $y1->id,
]);
$classA->setMeta('max_size', 30);
```

📦 Example: WMS
--------------

[](#-example-wms)

```
$wh = OU::create(['name' => 'Warehouse 1', 'type' => 'warehouse']);
$zone = OU::create(['name' => 'Zone A', 'parent_id' => $wh->id]);
$aisle = OU::create(['name' => 'Aisle 12', 'parent_id' => $zone->id]);
$bin = OU::create(['name' => 'Bin 7', 'parent_id' => $aisle->id]);

$bin->setMeta('max_weight', 250);
```

🏛️ Example: Facilities
----------------------

[](#️-example-facilities)

```
$campus = OU::create(['name' => 'North Campus']);
$building = OU::create(['name' => 'Block A', 'parent_id' => $campus->id]);
$room101 = OU::create(['name' => 'Room 101', 'parent_id' => $building->id']);
$room101->setMeta('capacity', 40);
```

⚙️ Extensibility
----------------

[](#️-extensibility)

- Attach any model via `entity_type/entity_id`
- Add metadata dynamically
- Use `type` to build domain-specific trees
- Use `tenant_id` for SaaS isolation

🔧 Performance Notes
-------------------

[](#-performance-notes)

- Bigint PKs allow fast joins and small indexes
- Narrow row design supports millions of units
- Typed metadata avoids unbounded JSON blobs
- Recursion is PHP-based for reliability

🧱 Philosophy Summary
--------------------

[](#-philosophy-summary)

- A **universal tree system**
- A **universal metadata system**
- A **universal linking system**
- Extendable into any domain
- Highly scalable and predictable

Example Domains
---------------

[](#example-domains)

[Example Domains](docs/docs.md)

This solves a problem once so your whole ecosystem doesn't need to reinvent structure management repeatedly.

###  Health Score

18

—

LowBetter than 10% of packages

Maintenance54

Moderate activity, may be stable

Popularity0

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity12

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.

### Community

Maintainers

![](https://www.gravatar.com/avatar/6e2afdd94a6f21a4ec2c5df569b80c1d47d6f5d0428f866f55c4bc117856b58b?d=identicon)[Ron Appleton](/maintainers/Ron%20Appleton)

---

Top Contributors

[![ronappleton](https://avatars.githubusercontent.com/u/3792420?v=4)](https://github.com/ronappleton "ronappleton (32 commits)")

### Embed Badge

![Health badge](/badges/ronappleton-organisational-unit/health.svg)

```
[![Health](https://phpackages.com/badges/ronappleton-organisational-unit/health.svg)](https://phpackages.com/packages/ronappleton-organisational-unit)
```

PHPackages © 2026

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