Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/bartko-s/stefano-tree
Framework agnostic Nested Set (MPTT) implementation for PHP
https://github.com/bartko-s/stefano-tree
doctrine-dbal doctrine2 hierarchical-data laminas laminas-db mptt nested-set pdo tree tree-structure zend-framework
Last synced: about 2 months ago
JSON representation
Framework agnostic Nested Set (MPTT) implementation for PHP
- Host: GitHub
- URL: https://github.com/bartko-s/stefano-tree
- Owner: bartko-s
- License: bsd-3-clause
- Created: 2013-06-02T18:19:45.000Z (over 11 years ago)
- Default Branch: master
- Last Pushed: 2023-11-27T20:31:31.000Z (about 1 year ago)
- Last Synced: 2024-09-21T13:36:14.351Z (3 months ago)
- Topics: doctrine-dbal, doctrine2, hierarchical-data, laminas, laminas-db, mptt, nested-set, pdo, tree, tree-structure, zend-framework
- Language: PHP
- Homepage: https://bartko-s.github.io/stefano-tree
- Size: 550 KB
- Stars: 28
- Watchers: 3
- Forks: 8
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.md
Awesome Lists containing this project
README
# Tree
[![Latest Stable Version](https://poser.pugx.org/stefano/stefano-tree/version)](https://packagist.org/packages/stefano/stefano-tree)
[![Build Status](https://app.travis-ci.com/bartko-s/stefano-tree.svg?branch=master)](https://app.travis-ci.com/bartko-s/stefano-tree)
[![Coverage Status](https://coveralls.io/repos/github/bartko-s/stefano-tree/badge.svg?branch=master)](https://coveralls.io/github/bartko-s/stefano-tree?branch=master)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/bartko-s/stefano-tree/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/bartko-s/stefano-tree/?branch=master)
[![License](https://poser.pugx.org/stefano/stefano-tree/license)](https://packagist.org/packages/stefano/stefano-tree)
[![Total Downloads](https://poser.pugx.org/stefano/stefano-tree/downloads)](https://packagist.org/packages/stefano/stefano-tree)
[![Monthly Downloads](https://poser.pugx.org/stefano/stefano-tree/d/monthly)](https://packagist.org/packages/stefano/stefano-tree)[![Buy me a coffee](./doc/buy-me-a-coffe.png)](https://www.buymeacoffee.com/bartko)
[![Donate on PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://paypal.me/stevo4)
[Nested Set](https://en.wikipedia.org/wiki/Nested_set_model) implementation for PHP.
[![Live demo](./doc/live-demo.jpg)](https://www.tree.stefanbartko.sk)
## Features
- NestedSet(MPTT - Modified Pre-order Tree Traversal)
- Support scopes (multiple independent tree in one db table)
- Rebuild broken tree
- Tested with MySQL/MariaDB and PostgreSQL but should work with any database vendor which support transaction
- Supported [PDO](http://php.net/manual/en/intro.pdo.php), [Zend Framework 1](https://framework.zend.com/manual/1.12/en/zend.db.html), [Laminas Db](https://github.com/laminas/laminas-db), [Doctrine 2 DBAL and Doctrine 3 DBAL](http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/). It is easy to implement support for any framework
- Support nested transaction
- PHP 7 and PHP 8 support## Dependencies
- This library has no external dependencies. Can work with pure PHP.## Installation
Run following command in terminal
```
composer require stefano/stefano-tree
```## Create Tree Adapter
| key | type | required | default value | note |
| :----------------- | :----: | :------: | :------------ | :---------------------------------------------------- |
| tableName | string | yes | | |
| idColumnName | string | yes | | |
| leftColumnName | string | no | lft | |
| rightColumnName | string | no | rgt | |
| levelColumnName | string | no | level | |
| parentIdColumnName | string | no | parent_id | |
| sequenceName | string | see note | | Required for PostgreSQL |
| scopeColumnName | string | see note | | If empty scope support is disabled |
| dbSelectBuilder | callable | no | | see Join table example below |```
use \StefanoTree\NestedSet;$options = array(
'tableName' => 'tree_traversal',
'idColumnName' => 'tree_traversal_id',
// other options
);$dbAdapter = pure \PDO, Zend1 Db Adapter, Laminas Db Adapter, Doctrine DBAL Connection or any class which implements StefanoTree\NestedSet\Adapter\AdapterInterface interface
$tree = new NestedSet($options, $dbAdapter);
```- You can join table.
```
$options = array(
'tableName' => 'tree_traversal',
'idColumnName' => 'tree_traversal_id',
'dbSelectBuilder' => function() {
// You can use any "callable" like function or object
// Select must be without where or order part
return 'SELECT tree_traversal.*, m.something, ...'
.' FROM tree_traversal'
.' LEFT JOIN metadata AS m ON tree_traversal.id=m.tree_id';
},
// other options
);$tree = new NestedSet($options, $dbAdapter);
```## API
### Creating nodes
- Create root node
```
use StefanoTree\Exception\ValidationException;try {
$data = array(
// values
// id_column_name => uuid
);
// create root node.
$rootNodeId = $tree->createRootNode($data);
// create root node. Second param "$scope" is required only if scope support is enabled.
$rootNodeId = $tree->createRootNode($data, $scope);
} catch (ValidationException $e) {
$errorMessage = $e->getMessage();
}
```- Create new node. You can create new node at 4 different locations.
![placements](./doc/placements.png)
```
use StefanoTree\Exception\ValidationException;try {
$targetNodeId = 10;
$data = array(
// values
// id_column_name => uuid
);$nodeId = $tree->addNode($targetNodeId, $data, $tree::PLACEMENT_CHILD_TOP);
$nodeId = $tree->addNode($targetNodeId, $data, $tree::PLACEMENT_CHILD_BOTTOM);
$nodeId = $tree->addNode($targetNodeId, $data, $tree::PLACEMENT_TOP);
$nodeId = $tree->addNode($targetNodeId, $data, $tree::PLACEMENT_BOTTOM);
} catch (ValidationException $e) {
$errorMessage = $e->getMessage();
}
```### Update Node
```
use StefanoTree\Exception\ValidationException;try {
$targetNodeId = 10;
$data = array(
// values
);
$tree->updateNode($targetNodeId, $data);
} catch (ValidationException $e) {
$errorMessage = $e->getMessage();
}
```### Move node
- You can move node at 4 different locations.
![placements](./doc/placements.png)
```
use StefanoTree\Exception\ValidationException;try {
$sourceNodeId = 15;
$targetNodeId = 10;
$tree->moveNode($sourceNodeId, $targetNodeId, $tree::PLACEMENT_CHILD_TOP);
$tree->moveNode($sourceNodeId, $targetNodeId, $tree::PLACEMENT_CHILD_BOTTOM);
$tree->moveNode($sourceNodeId, $targetNodeId, $tree::PLACEMENT_TOP);
$tree->moveNode($sourceNodeId, $targetNodeId, $tree::PLACEMENT_BOTTOM);
} catch (ValidationException $e) {
$errorMessage = $e->getMessage();
}
```### Delete node or branch
```
use StefanoTree\Exception\ValidationException;try {
$nodeId = 15;
$tree->deleteBranch($nodeId);
} catch (ValidationException $e) {
$errorMessage = $e->getMessage();
}
```### Getting nodes
- Get descendants
```
$nodeId = 15;// all descendants
$tree->getDescendantsQueryBuilder()
->get($nodeId);
// all descendants result as nested array
$tree->getDescendantsQueryBuilder()
->get($nodeId, true);
// only children
$tree->getDescendantsQueryBuilder()
->excludeFirstNLevel(1)
->levelLimit(1)
->get($nodeId);// exclude first level($nodeId) from result
$tree->getDescendants()
->excludeFirstNLevel(1)
->get($nodeId);// exclude first two levels from result
$tree->getDescendantsQueryBuilder()
->excludeFirstNLevel(2)
->get($nodeId);// return first 4 level
$tree->getDescendantsQueryBuilder()
->levelLimit(4)
->get($nodeId);// exclude branch from result
$tree->getDescendantsQueryBuilder()
->excludeBranch(22)
->get($nodeId);
```- Get Ancestors
```
$nodeId = 15;// get all
$tree->getAncestorsQueryBuilder()
->get($nodeId);
// get all as nested array
$tree->getAncestorsQueryBuilder()
->get($nodeId, true);// exclude last node($nodeId) from result
$tree->getAncestorsQueryBuilder()
->excludeLastNLevel(1)
->get($nodeId);// exclude first two levels from result
$tree->getAncestorsQueryBuilder()
->excludeFirstNLevel(2)
->get($nodeId);
```### Validation and Rebuild broken tree
- Check if tree is valid
```
use StefanoTree\Exception\ValidationException;try {
$satus = $tree->isValid($rootNodeId);
} catch (ValidationException $e) {
$errorMessage = $e->getMessage();
}
```- Rebuild broken tree
```
use StefanoTree\Exception\ValidationException;try {
$tree->rebuild($rootNodeId);
} catch (ValidationException $e) {
$errorMessage = $e->getMessage();
}
```## Contributing
Any contributions are welcome. If you find any issue don't hesitate to open a new issue or send a pull request.
[![Buy me a coffee](./doc/buy-me-a-coffe.png)](https://www.buymeacoffee.com/bartko)