PHPackages                             girover/tree - 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. girover/tree

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

girover/tree
============

Building family tree

1.0.1(3y ago)19MITPHPPHP ^8.0

Since Jun 22Pushed 3y ago1 watchersCompare

[ Source](https://github.com/girover/laravel-family-tree-builder)[ Packagist](https://packagist.org/packages/girover/tree)[ Docs](https://github.com/girover/laravel-family-tree)[ RSS](/packages/girover-tree/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (8)Versions (3)Used By (0)

[![tree-template-3](https://user-images.githubusercontent.com/53403538/137398258-c43cba4a-8257-442a-9e0d-4c49f5e529d7.png)](https://user-images.githubusercontent.com/53403538/137398258-c43cba4a-8257-442a-9e0d-4c49f5e529d7.png)

Building Family Tree
====================

[](#building-family-tree)

[![Latest Version on Packagist](https://camo.githubusercontent.com/a5a410703681924bb1bf5370c40e8afad5b993d4ba1ef9733230d420482749bf/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6769726f7665722f747265652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/girover/tree)[![GitHub Tests Action Status](https://camo.githubusercontent.com/a2b662af4c7e8b37b39695d60868cbf506c5f502bf3abf4d503824dc76e91734/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f776f726b666c6f772f7374617475732f6769726f7665722f747265652f72756e2d74657374733f6c6162656c3d7465737473)](https://github.com/girover/tree/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/8471d7562dc107afd080863fd89d5e3b21568a0f78f631a8fd52445a927c6d9c/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f776f726b666c6f772f7374617475732f6769726f7665722f747265652f436865636b253230262532306669782532307374796c696e673f6c6162656c3d636f64652532307374796c65)](https://github.com/girover/tree/actions?query=workflow%3A%22Check+%26+fix+styling%22+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/55e169b1414e072a9b6a7d1bd65b1b998ee256146ac0bd7b8685af977fe78d80/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6769726f7665722f747265652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/girover/tree)

---

Content
-------

[](#content)

- [Introduction](#introduction)
- [prerequisites](#prerequisites)
- [Installation](#installation)
- [Assets](#assets)
- [Images](#images)
- [Usage](#usage)
    - [Treeable Model](#treeable-model)
    - [Pointer](#pointer)
    - [Nodeable Model](#nodeable-model)
        - [Retrieving nodes](#retrieving-nodes)
        - [Adding nodes](#adding-nodes)
        - [Deleting nodes](#deleting-nodes)
        - [Checking nodes](#checking-nodes)
        - [Relationships](#relationships)
        - [Relocating nodes](#relocating-nodes)
        - [Attaching and Detaching nodes](#attaching-and-detaching)
    - [Helpers](#helpers)
    - [Rendering Trees](#rendering-trees)
    - [Customizing node style](#customizing-node-style)
- [Testing](#testing)
- [Changelog](#changelog)
- [Contributing](#contributing)
- [Security Vulnerabilities](#security-vulnerabilities)
- [Credits](#credits)
- [License](#license)

Introduction
------------

[](#introduction)

**girover/laravel-family-tree** is a package that allows you to build family trees. With this package it will be very simple to create trees and add nodes to trees.

Every tree is allowed to have 85 generations. Assuming each generation has 20 years, this means that 1700 years of data can be stored in one tree.
Every node in a tree is allowed to have 676 direct children.

prerequisites
-------------

[](#prerequisites)

- Laravel 8+
- PHP 8+
- Mysql 5.7+

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

[](#installation)

You can add the package via **composer**:

```
composer require girover/laravel-family-tree
```

Before installing the package you should configure your database.

Then you can install the package by running Artisan command

```
php artisan tree:install
```

this command will take care of the following tasks:

- Publishing Config file `config\tree.php` to the config folder of your Laravel application.
- Publishing migration files to folder `Database\migrations` in your application.
- Migrate the published migrations.
- Publishing Assets **(css, js, images)** to the public folder in your application and they will be placed in `public\vendor\tree`.
- Publishing JSON Translation files to the `resources\lang\vendor\tree`

Assets
------

[](#assets)

After publishing assets (css, js, images), they will be placed in `public` folder of the project in a folder called `vendor/tree`. You are free to move any of these assets to other directories.

You should add the CSS file `vendor/tree/css/tree.css` to your blade file to get the tree styled.

Images
------

[](#images)

Every node in tree has an avatar photo. Male and Female Icons by default will be stored in the public folder under
`vendor/tree/images`.
however you are free to choose another folder for the images of nodes, but you must provide it in the `config\tree.php` file.

```
    'photos_folder' => 'path/to/your/images',
```

So your images folder should be in the **`public`** folder. Example: if images are stored in folder called `images/avatars` the configs must be:

```
    'photos_folder' => 'images/avatars',
```

**Note:** When saving photos in storage folder, it is important to create symbolic link to the photos folder.

Usage
=====

[](#usage)

To start building family trees, you must have two models. The first one represents trees in database and it must use the trait:
`\Girover\Tree\Traits\Treeable`
The second model represents nodes in these trees, and it must use trait:
`\Girover\Tree\Traits\nodeable`
***NOTE: The names of the models that represents trees and nodes in database must be provided in `config/tree.php`.***

```
    // config/tree.php
    return [
        /*
        |----------------------------------------------------------
        | Model That uses trait \Girover\Tree\Traits\Treeable
        |----------------------------------------------------------
        |
        | example: App\Models\Family::class
        */
        'treeable_model' => App\Models\Family::class,
        /*
        |----------------------------------------------------------
        | Model That uses trait \Girover\Tree\Traits\Nodeable
        |----------------------------------------------------------
        |
        | example: App\Models\Person::class
        */
        'nodeable_model' => App\Models\Person::class,
        .
        .
        .
```

Treeable Model
--------------

[](#treeable-model)

To start building a tree or creating a new tree, it is very simple and thanks to [Eloquent](https://laravel.com/docs/8.x/eloquent) models from [Laravel](http://laravel.com).
The model that represents trees in database should use **trait**: `\Girover\Tree\Traits\Treeable`For example if your model is called `Tree` so it should looks like this:

```
namespace App\Models;

use Girover\Tree\Traits\Treeable;

class Tree extends Model
{
    use Treeable;
}
```

And now you can use your model to deal with trees.

```
use App\Models\Tree;

$tree = Tree::create(
    [
        'info' => 'info',
        'another_info' => 'another info',
    ]
);
```

After creating the tree, you can start to add as many nodes as you want.
Let's start adding the First node, the **`Root`**, to the tree.

```
    $data = ['name'=>'root', 'birth_date'=>'2000-01-01'];

    $tree->createRoot($data);
```

**What if you want to make a new Root?**
In this case you can use the method **`newRoot`**, and the previously created Root will become a child of the new created Root.

```
    $new_root_data = ['name'=>'new_root', 'birth_date'=>'2001-01-01'];

    $tree->newRoot($new_root_data);
```

After creating the Root in the tree, let's add first child for the Root.

```
    use Girover\Tree\Models\Tree;

    $tree = Tree::find(1);

    $first_child_data = ['name'=>'first child', 'birth_date'=>'2001-01-01'];

    $tree->pointerToRoot()->newChild($first_child_data ,'m'); // m = male

    // Or you can do this instead
    $tree->pointerToRoot()->newSon($first_child_data);
```

Now our tree consists of two nodes, the root and the first child of the root.

You can call the following method on an object of Tree

\#MethodDescriptionParams1`createRoot($data)`create root in the tree.`$data` is array of root info2`newRoot($data)`makes new root for the tree.`$data` is array of info for the new root3`toHtml()`convert the tree to html to view it4`draw()`convert the tree to html to view it5`toTree()`convert the tree to html to view it6`emptyTree()`return an empty tree to view it7`pointer()`To get the pointer inside the tree8`pointerToRoot()`To move the pointer to indicate to the root9`pointerTo($nodeable)`To move the pointer to the given node10`goTo($nodeable)`To move the pointer to the given node14`countGenerations()`To get how many generations this tree has15`nodesOnTop()`Get the newest generation members in the tree16`mainNode()`Get the main node in the treePointer
-------

[](#pointer)

A tree has a **Pointer** inside it, and this **Pointer** points to one node.
Pointer can move through all nodes in the tree.
Because the Pointer points to a **node** inside the tree, so it can call all [methods of model that uses Nodeable Trait](#node) .
To get the pointer you can do the following:

```
    use App\Models\Tree;

    $tree    = Tree::find(1);
    $pointer = $tree->pointer();
```

And now you can use the pointer to make a lot of actions inside the tree, for example moving through nodes, deleting and retrieving more information about nodes.
Eg. To move the pointer to specific node:

```
    use App\Models\Tree;
    use App\Models\Node;

    $tree    = Tree::find(1);
    $node    = Node::find(10);

    $tree->pointer()->to($node);
```

And now you can get the node data by calling the method `node`

```
    $node = $pointer->node();
    echo $node->attribute_1;
    echo $node->attribute_2;
    echo $node->attribute_3;
```

Note that we called method `node` after we had called the method `to($node)`.
This is because when a tree object is created, its **Pointer** indicates to `null`.

Nodeable Model
--------------

[](#nodeable-model)

- [What is a node](#what-is-a-node)
- [Retrieving nodes](#retrieving-nodes)
- [Adding nodes](#adding-nodes)
- [Deleting nodes](#deleting-nodes)
- [Checking nodes](#checking-nodes)
- [Relationships](#relationships)
- [Relocating nodes](#relocating-nodes)
- [Attaching and Detaching nodes](#attaching-and-detaching)

### What is a node

[](#what-is-a-node)

**Node** is a **person** in a tree and every node in the tree is connected with another one by using **Location mechanism**.

To retrieve a nodes you can use Eloquent model that uses trait `Girover\Tree\Traits\Nodeable`

```
    use App\Models\Node;

    $node    = Node::find(1);
```

### Retrieving nodes

[](#retrieving-nodes)

To get the tree that the node belongs to.

```
    $node->getTree();
```

To get the father of the node:

```
    return $node->father();
```

To get the grandfather of the node:

```
    return $node->grandfather();
```

To get the ancestor that matches the given number as parameter.

```
    $node->ancestor(); // returns father
    $node->ancestor(2); // returns grandfather
    $node->ancestor(3); // returns the father of grandfather
```

To get all ancestors of a node

```
    return $node->ancestors();
```

To get all uncles of the node:

```
    return $node->uncles();
```

To get all aunts of the node:

```
    return $node->aunts();
```

To get all children of the node:

```
    return $node->children();
```

To get all sons of the node:

```
    return $node->sons();
```

To get all daughters of the node:

```
    return $node->daughters();
```

To get all descendants of the node:

```
    return $node->descendants();
```

To get all male descendants of the node:

```
    return $node->maleDescendants();
```

To get all female descendants of the node:

```
    return $node->femaleDescendants();
```

To get the first child of the node:

```
    return $node->firstChild();
```

To get the last child of the node:

```
    return $node->lastChild();
```

To get all siblings of the node:

```
    return $node->siblings();
```

To get all brothers of the node:

```
    return $node->brothers();
```

To get all sisters of the node:

```
    return $node->sisters();
```

To get the next sibling of the node. gets only one sibling.

```
    return $node->nextSibling();
```

To get all the next siblings of the node. siblings who are younger.

```
    return $node->nextSiblings();
```

To get the next brother of the node. gets only one brother.

```
    return $node->nextBrother();
```

To get all the next brothers of the node. brothers who are younger.

```
    return $node->nextBrothers();
```

To get the next sister of the node. gets only one sister.

```
    return $node->nextSister();
```

To get all the next sisters of the node. sisters who are younger.

```
    return $node->nextSisters();
```

To get the previous sibling of the node. only one sibling.

```
    return $node->prevSibling();
```

To get all the previous siblings of the node. siblings who are older.

```
    return $node->prevSiblings();
```

To get the previous brother of the node. only one brother.

```
    return $node->prevBrother();
```

To get all the previous brothers of the node. brothers who are older.

```
    return $node->prevBrothers();
```

To get the previous sister of the node. only one sister.

```
    return $node->prevSister();
```

To get all the previous sisters of the node. sisters who are older.

```
    return $node->prevSisters();
```

To get the first sibling of the node.

```
    return $node->firstSibling();
```

To get the last sibling of the node.

```
    return $node->lastSibling();
```

To get the first brother of the node.

```
    return $node->firstBrother();
```

To get the last brother of the node.

```
    return $node->lastBrother();
```

To get the first sister of the node.

```
    return $node->firstSister();
```

To get the last sister of the node.

```
    return $node->lastSister();
```

### Adding nodes

[](#adding-nodes)

The next code will create father for a node, only if this node is a Root in the tree.
If the node is not a `root`, `Girover\Tree\Exceptions\TreeException` will be thrown.

```
    $data = ['name' => $name, 'birth_date' => $birth_date];
    $node->createFather($data);
    // OR
    $tree = Tree::find(1);
    $tree->pointerToRoot()->createFather($data);
```

To create new sibling for the node:

```
    $data = ['name'=>$name, 'birth_date'=>$birth_date];

    return $node->newSibling($data, 'm'); // m = male
```

To create new brother for the node:

```
    $data = ['name'=>$name, 'birth_date'=>$birth_date];
    $node->newBrother($data);

    // or you can use the newSibling method
    $node->newSibling($data, 'm');
```

To create new sister for the node:

```
    $data = ['name'=>$name, 'birth_date'=>$birth_date];
    $node->newSister($data);

    // or you can use the newSibling method
    $node->newSibling($data, 'f');
```

To create new son for the node:

```
    $data = ['name'=>$name, 'birth_date'=>$birth_date];
    $node->newSon($data);

    // or you can use the newChild method
    $node->newChild($data, 'm');
```

To create new daughter for the node:

```
    $data = ['name'=>$name, 'birth_date'=>$birth_date];
    $node->newDaughter($data);

    // or you can use the newChild method
    $node->newChild($data, 'f');
```

To make the node as the main node in its tree.

```
    $node->makeAsMainNode();
```

### Deleting nodes

[](#deleting-nodes)

To delete a node.

```
    use App\Models\Person;

    $node = Person::find(10)->delete();
```

**note:** The node will be deleted with all its descendants.
But if you want just to delete the node and not its descendants,
then you can move its descendants before deleting the node.

```
    use App\Models\Person;

    $node = Person::find(10);
    $another_node = Person::find(30);

    $node->moveChildrenTo($another_node);
    $node->delete();
```

Or you can directly move children to the father of deleted node by using `onDeleteMoveChildren` method without passing any node as parameter.

```
    use App\Models\Person;

    $node = Person::find(10);

    $node->onDeleteMoveChildren()->delete();
```

To delete all children of a node:

```
    use App\Models\Person;

    $node = Person::find(10);

    return $node->deleteChildren(); // number of deleted nodes
```

### Checking nodes

[](#checking-nodes)

To determine if the node is root in the tree

```
    return $node->isRoot(); // returns true or false
```

To determine if the node is ancestor of another node:

```
    use App\Models\Person;

    $node = Person::find(1);
    $another_node = Person::find(2);

    return $node->isAncestorOf($another_node); // returns true OR false
```

To determine if the node is father of another node:

```
    use App\Models\Person;

    $node = Person::find(1);
    $another_node = Person::find(2);

    return $node->isFatherOf($another_node); // returns true OR false
```

Determine if the node has children

```
    return $node->hasChildren(); // returns true or false
```

To determine if the node is child of another node:

```
    use App\Models\Person;

    $node = Person::find(1);
    $another_node = Person::find(2);

    return $node->isChildOf($another_node); // returns true OR false
```

Determine if the node has siblings

```
    return $node->hasSiblings(); // returns true or false
```

To determine if the node is sibling of another node:

```
    use App\Models\Person;

    $node = Person::find(1);
    $another_node = Person::find(2);

    return $node->isSiblingOf($another_node); // returns true OR false
```

To count the children of the node:

```
    return $node->countChildren();
```

To count sons of a node:

```
    return $node->countSons();
```

To count daughters of the node:

```
    return $node->countDaughters();
```

To count all siblings of the node:

```
    return $node->countSiblings();
```

To count all brothers of the node:

```
    return $node->countBrothers();
```

To count all sisters of the node:

```
    return $node->countSisters();
```

To count all descendants of the node:

```
    return $node->countDescendants();
```

To count all male descendants of the node:

```
    return $node->countMaleDescendants();
```

To count all female descendants of the node:

```
    return $node->countFemaleDescendants();
```

### Relationships

[](#relationships)

To get all wives of the node:

```
    $node->wives;
    // to add constraints
    $node->wives()->where('name', $name)->get();
```

When trying to get wives of female node a `Girover\Tree\Exceptions\TreeException` will be thrown.
Note that this will get divorced wives too.
To get only wives who are not divorced you can do this:

```
    $node->wives()->ignoreDivorced()->get();
```

To get husbands of the node:

```
    $node->husband;
    // to add constraints
    $node->husband()->where('name', $name)->get();
```

When trying to get husband of male node a `Girover\Tree\Exceptions\TreeException` will be thrown.
Note that this will get divorced husbands too.
To get only husbands who are not divorced you can do this:

```
    $node->husband()->ignoreDivorced()->get();
```

To assign wife to a node:

```
    $wife = Node::find($female_node_id)
    $data = ['date_of_marriage'=>'2000/01/01', 'marriage_desc'=>'description'];

    return $node->getMarriedWith($wife, $data);
```

When trying to do this with a female node (woman) a `Girover\Tree\Exceptions\TreeException` will be thrown. so if `$node` is a woman Exception will be thrown.

To divorce a wife

```
    $husband = Node::find($male_node_id)
    $wife    = Node::find($female_node_id)

    return $husband->divorce($wife);
```

When trying to do this with a female node a `Girover\Tree\Exceptions\TreeException` will be thrown. so if `$husband` is a woman Exception will be thrown.

To set uploaded photo to the node:

```
