PHPackages                             simpeldigitaal/tree-model - 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. [Database &amp; ORM](/categories/database)
4. /
5. simpeldigitaal/tree-model

ActiveLibrary[Database &amp; ORM](/categories/database)

simpeldigitaal/tree-model
=========================

Adds a tree to Eloquent Models.

00PHP

Since Dec 11Pushed 7y agoCompare

[ Source](https://github.com/simpelDigitaal/treeModel)[ Packagist](https://packagist.org/packages/simpeldigitaal/tree-model)[ RSS](/packages/simpeldigitaal-tree-model/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

TreeModel
=========

[](#treemodel)

Use Cases
---------

[](#use-cases)

A TreeModel, or **nested subset**, is especially usefull for storing and retreiving the complete *tree* of subsequent models. It will prevent many queries while building the layout, like:

- level 1 - A
    - level 2 - AA
        - level 3 - AAA
        - level 3 - AAB
            - level 4 - AABA
            - ...
    - level 2 - AB
    - ...
- ...

Examples for use is a menu for pages or categories.

It could also be used to count all underlying related models, for example all `products` in a category and underlying categories:

```
$allCategories = $category->allChildren()->select(id);

$productCount = Product::whereHas('categories', function ($query) use ($allCategories, $category) {
    $query->whereIn('id', $allCategories);
    $query->orWhere('id', '=', $category->id);
})->count();
```

*(note: this is just pseudocode, propably not working)*

Using TreeModel
---------------

[](#using-treemodel)

This package has 2 core-functionalities: the migration-helper and a relation to be included inside an Eloquent Model. The migration-helper will be included using the TreeModelServiceProvider, however, the relation will also work without it.

### Install

[](#install)

Require this package with composer.

```
composer require simpeldigitaal/tree-model
```

If you don't use auto-discovery, add the ServiceProvider to the providers array in config/app.php

```
SimpelDigitaal\TreeModel\TreeModelServiceProvider::class
```

### Use

[](#use)

#### Inside your migration:

[](#inside-your-migration)

**up**

```
    public function up()
    {
        Schema::table('menu', function (Blueprint $table) {
            ...
            $table->tree();
            ...
        });

        Schema::table('categories', function (Blueprint $table) {
            ...
            $table->treeWithId();
            ...
        });
    }
```

`$table->tree($prefix = 'tree');`Generates the necessary fields for storing the tree (*tree\_start* and *tree\_end*). You are able to change the default prefix.

`$table->treeWithId($name = 'parent_id', $prefix = 'tree');`Generates besides the necessary fields for storing the tree the parent-child relation too. This field may be used in a `HasMany` or `BelongsTo` relation.

**and down**

```
    public function down()
    {
        Schema::table('menu', function (Blueprint $table) {
            ...
            $table->dropTree();
            ...
        });

        Schema::table('categories', function (Blueprint $table) {
            ...
            $table->dropTreeWithId();
            ...
        });

    }
```

`$table->dropTree($prefix = 'tree');` Drops the fields for the tree.

`$table->dropTreeWithId($name = 'parent_id', $prefix = 'tree');` Drops the field for the parent-child relation too...

#### Inside your model:

[](#inside-your-model)

Include the `SimpelDigitaal\WebTree\Concerns\HasTree`-trait to your Eloquent-Model.

On top:

```
use SimpelDigitaal\WebTree\Concerns\HasTree;
```

Inside your model:

```
class Categories extends Model {

    use HasTree
    ...
    public function allChildren()
    {
        return $this->getTree();
    }

    public function childrenFromTree()
    {
        return $this->getSubsetTree('allChildren');
    }
    ...
}
```

`getTree` will fetch all children from the database. `childrenFromTree` will fetch the subset for the next level, seeding all children with their own subset. It will use and it will set the relation specified as first parameter.

#### Building the tree.

[](#building-the-tree)

After storing a new model or changing an existing model, you have to build the tree again using `$model->buildsTree()`;

#### Building layout:

[](#building-layout)

Example:

```
    $categories = Category::whereNull('parent_id')->with('allChildren')->get();
```

```

    @foreach($categories as $category)

            {{ $category->name }} | {{ $category->treeStart }} - {{ $category->treeEnd }}
            @include('categories._list', ['categories' => $category->childrenFromTree()])

    @endforeach

```

Builds with only two queries: first to retreive $categories, second for eagerloading relation 'allChildren'

### Enjoy

[](#enjoy)

Tips
----

[](#tips)

### Adding constraints

[](#adding-constraints)

If you want to add a constraint to your tree (for example a `site_id`), you are able to set this constraint using a [global scope](https://laravel.com/docs/5.7/eloquent#global-scopes).

Sources
-------

[](#sources)

- [Inspired by the 'nested set' of the Joomla-framework](https://docs.joomla.org/Using_nested_sets)
    - [Especially this article, from Gijs Van Tulder](https://www.sitepoint.com/hierarchical-data-database/)
    - [Wikipedia about this 'Tree'](https://en.wikipedia.org/wiki/Nested_set_model)

###  Health Score

17

—

LowBetter than 6% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity38

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/f7974302cb29865ee6d3131f286431d20566779da2ceb22b0852c1383f02b71d?d=identicon)[simpeldigitaal](/maintainers/simpeldigitaal)

---

Top Contributors

[![uniels](https://avatars.githubusercontent.com/u/12213461?v=4)](https://github.com/uniels "uniels (7 commits)")

### Embed Badge

![Health badge](/badges/simpeldigitaal-tree-model/health.svg)

```
[![Health](https://phpackages.com/badges/simpeldigitaal-tree-model/health.svg)](https://phpackages.com/packages/simpeldigitaal-tree-model)
```

###  Alternatives

[doctrine/orm

Object-Relational-Mapper for PHP

10.2k285.3M6.2k](/packages/doctrine-orm)[jdorn/sql-formatter

a PHP SQL highlighting library

3.9k115.1M102](/packages/jdorn-sql-formatter)[illuminate/database

The Illuminate Database package.

2.8k52.4M9.3k](/packages/illuminate-database)[mongodb/mongodb

MongoDB driver library

1.6k64.0M542](/packages/mongodb-mongodb)[ramsey/uuid-doctrine

Use ramsey/uuid as a Doctrine field type.

90340.3M209](/packages/ramsey-uuid-doctrine)[reliese/laravel

Reliese Components for Laravel Framework code generation.

1.7k3.4M16](/packages/reliese-laravel)

PHPackages © 2026

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