PHPackages                             alto/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. [File &amp; Storage](/categories/file-storage)
4. /
5. alto/tree

ActiveLibrary[File &amp; Storage](/categories/file-storage)

alto/tree
=========

A modern PHP library for building, parsing, traversing, and printing tree structures representing file and directory hierarchies

v1.0.0(5mo ago)12MITPHPPHP ^8.2CI passing

Since Jan 16Pushed 5mo agoCompare

[ Source](https://github.com/PhpAlto/tree)[ Packagist](https://packagist.org/packages/alto/tree)[ Docs](https://github.com/phpalto/tree)[ GitHub Sponsors](https://github.com/sponsors/smnandre)[ RSS](/packages/alto-tree/feed)WikiDiscussions main Synced today

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

Alto \\ Tree
============

[](#alto--tree)

A modern PHP library for building, parsing, traversing, and printing tree structures representing file and directory hierarchies.

---

 [![PHP Version](https://camo.githubusercontent.com/c4d5b0981e76e91ecf0c352aab5e81442c79fbbd0acb7e719f38b589626f0f0e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e322b2d6666656664663f6c6f676f436f6c6f723d7768697465266c6162656c436f6c6f723d303030)](https://github.com/PhpAlto/tree) [![CI](https://camo.githubusercontent.com/475f7cfe28f66c502c88b6e95c2a38885d70a862f1840ae2d2802896bb85fa82/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f506870416c746f2f747265652f43492e796d6c3f6272616e63683d6d61696e266c6162656c3d5465737473266c6f676f436f6c6f723d7768697465266c6f676f53697a653d6175746f266c6162656c436f6c6f723d30303026636f6c6f723d666665666466)](https://github.com/PhpAlto/tree/actions) [![Packagist Version](https://camo.githubusercontent.com/07d9c6ac226d15056f7f21468b980a698afcd839ed145fc277e79588773bdcfe/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f616c746f2f747265653f6c6162656c3d537461626c65266c6f676f436f6c6f723d7768697465266c6f676f53697a653d6175746f266c6162656c436f6c6f723d30303026636f6c6f723d666665666466)](https://packagist.org/packages/alto/tree) [![PHP Version](https://camo.githubusercontent.com/79820ea4fbf7ba81b487f71ba6cd7cc3990b572b950544e8be10876f72a81ba7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f504850556e69742d3130302532352d6666656664663f6c6f676f436f6c6f723d7768697465266c6162656c436f6c6f723d303030)](https://github.com/PhpAlto/tree) [![PHP Version](https://camo.githubusercontent.com/46cab1ca7fbef6e1ecb3fcb46ebda03c929e31a141d14b601a9ecbfc868873d5/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d4c564c25323031302d6666656664663f6c6f676f436f6c6f723d7768697465266c6162656c436f6c6f723d303030)](https://github.com/PhpAlto/tree) [![License](https://camo.githubusercontent.com/aca03aeea174ecd84ec4765338d64a64859383e468b14e39749e8b76bd87a5ff/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f506870416c746f2f747265653f6c6162656c3d4c6963656e7365266c6f676f436f6c6f723d7768697465266c6f676f53697a653d6175746f266c6162656c436f6c6f723d30303026636f6c6f723d666665666466)](./LICENSE)

Why Alto Tree?
--------------

[](#why-alto-tree)

Alto Tree makes it easy to work with hierarchical file structures in PHP. Whether you need to:

- Visualize directory structures in your CLI tools
- Parse output from the `tree` command
- Analyze project organization
- Generate documentation with file trees
- Compare or merge directory structures

Alto Tree provides a clean, type-safe API with comprehensive documentation and examples.

Features
--------

[](#features)

- **Build Trees**: Create tree structures from arrays of file/directory paths
- **Parse Trees**: Parse string representations of trees in multiple formats (ASCII art, bullets, indented)
- **Print Trees**: Generate beautiful ASCII art representations of tree structures
- **Traverse Trees**: Use the visitor pattern to traverse and analyze tree structures
- **Manipulate Trees**: Split, merge, and append operations on tree nodes
- **Compare Trees**: Diff two trees to identify added, removed, and unchanged nodes
- **Type-Safe**: Fully typed with PHP 8.2+ features and strict types
- **Well-Tested**: Comprehensive test coverage with PHPUnit
- **Modern**: PSR-12 compliant, uses modern PHP features

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

[](#requirements)

- PHP 8.2 or higher

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

[](#installation)

Install via Composer:

```
composer require alto/tree
```

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

[](#quick-start)

### Basic Example

[](#basic-example)

```
use Alto\Tree\TreeBuilder;
use Alto\Tree\Printer\TreePrinter;

// Build a tree from paths
$paths = ['src/Controller/HomeController.php', 'src/Entity/User.php'];
$tree = TreeBuilder::fromPaths($paths, 'my-app');

// Print the tree
$printer = new TreePrinter();
echo $printer->print($tree);
```

### Build from Filesystem

[](#build-from-filesystem)

```
// Scan actual filesystem
$tree = TreeBuilder::fromFilesystem('/path/to/project', [
    'max_depth' => 3,
    'exclude' => ['vendor', 'node_modules'],
]);
```

### Build from Git Repository

[](#build-from-git-repository)

```
// Get git-tracked files
$tree = TreeBuilder::fromGit('/path/to/repo');

// Or get only modified files
$tree = TreeBuilder::fromGit('/path/to/repo', [
    'modified_only' => true,
]);
```

Usage
-----

[](#usage)

### Building Trees

[](#building-trees)

Alto Tree uses the **Provider Pattern** to support multiple data sources.

#### From Array of Paths

[](#from-array-of-paths)

```
use Alto\Tree\TreeBuilder;

$paths = [
    'src/Controller/HomeController.php',
    'src/Controller/UserController.php',
    'src/Entity/User.php',
];

$tree = TreeBuilder::fromPaths($paths, 'src');
```

#### From Filesystem

[](#from-filesystem)

Scan actual files and directories:

```
$tree = TreeBuilder::fromFilesystem('/path/to/project', [
    'max_depth' => 3,                    // Limit depth (default: unlimited)
    'exclude' => ['vendor', '.git'],     // Exclude patterns
    'include_hidden' => false,           // Include hidden files (default: false)
    'with_metadata' => true,             // Include file metadata (default: false)
]);
```

#### From Git Repository

[](#from-git-repository)

Build tree from git-tracked files:

```
// All tracked files
$tree = TreeBuilder::fromGit('/path/to/repo');

// Only modified files
$tree = TreeBuilder::fromGit('/path/to/repo', [
    'modified_only' => true,
]);

// Diff between branches
$tree = TreeBuilder::fromGit('/path/to/repo', [
    'diff' => 'main..feature',
]);

// Files from specific commit
$tree = TreeBuilder::fromGit('/path/to/repo', [
    'commit' => 'abc123',
]);
```

#### Custom Providers

[](#custom-providers)

Create your own provider for any data source:

```
use Alto\Tree\Provider\TreeSourceProviderInterface;
use Alto\Tree\Provider\NodeData;

class ComposerProvider implements TreeSourceProviderInterface
{
    public function getRootPath(): string { return 'dependencies'; }

    public function getNodes(): array
    {
        // Parse composer.lock, return NodeData objects
        return [
            new NodeData('vendor/package', true),
            new NodeData('vendor/package/src/File.php', false),
        ];
    }
}

$tree = TreeBuilder::from(new ComposerProvider());
```

### Parsing a Tree from String

[](#parsing-a-tree-from-string)

Parse a string representation of a tree back into a `Tree` object:

```
use Alto\Tree\Parser\TreeParser;

$input = traverse($tree);

echo $collector->getSummary();
// Output: Found 4 files and 3 directories

$files = $collector->getFiles();
$directories = $collector->getDirectories();
```

### Flattening a Tree

[](#flattening-a-tree)

Convert a tree structure into a flat array of paths:

```
use Alto\Tree\TreeFlattener;

$paths = TreeFlattener::flatten($tree);
// Returns: ['src/Controller', 'src/Controller/HomeController.php', ...]

// Rebuild a tree from paths
$newTree = TreeFlattener::buildTree($paths);
```

### Splitting a Tree

[](#splitting-a-tree)

Extract a subtree from a specific path:

```
$tree = TreeBuilder::fromPaths([
    'src/Controller/HomeController.php',
    'src/Entity/User.php'
]);

// Extract just the Controller subtree
$controllerTree = $tree->split('src/Controller');
```

### Merging Trees

[](#merging-trees)

Combine two trees into one:

```
$tree1 = TreeBuilder::fromPaths(['src/Controller/HomeController.php']);
$tree2 = TreeBuilder::fromPaths(['src/Entity/User.php']);

$merged = $tree1->merge($tree2);
// Now contains both Controller and Entity directories
```

### Appending Nodes

[](#appending-nodes)

Add a node as a child of another node:

```
$mainTree = TreeBuilder::fromPaths(['src/Controller/HomeController.php']);
$extraNode = TreeBuilder::fromPaths(['config/app.php']);

$result = $mainTree->append($extraNode, 'config');
// Adds the config tree as a child of mainTree
```

### Comparing Trees (Diff)

[](#comparing-trees-diff)

Compare two trees to identify changes:

```
use Alto\Tree\Diff\TreeDiff;
use Alto\Tree\Diff\DiffPrinter;

$oldTree = TreeBuilder::fromPaths(['project/src/App.php']);
$newTree = TreeBuilder::fromPaths([
    'project/src/App.php',
    'project/src/Router.php',  // Added
]);

$diff = TreeDiff::compare($oldTree, $newTree);

echo $diff->getSummary();  // "+1"
echo $diff->getDetailedSummary();  // "Added: 1 file"

// Print visual diff
$printer = new DiffPrinter();
echo $printer->print($diff);

// Get added/removed nodes
$added = $diff->getAdded();
$removed = $diff->getRemoved();
$unchanged = $diff->getUnchanged();
```

API Reference
-------------

[](#api-reference)

### Core Classes

[](#core-classes)

#### `Tree`

[](#tree)

**Final class** representing the root of a tree structure. Extends `TreeNode`.

#### `TreeNode`

[](#treenode)

Represents a node (file or directory) in the tree.

**Properties:**

- `string $path` - Full path to the node
- `string $name` - Base name (file/directory name)
- `bool $isDir` - Whether this is a directory
- `array $children` - Child nodes
- `?array $metadata` - Optional metadata (size, mtime, permissions, etc.)

**Metadata:**When using `with_metadata: true` option with FileSystemProvider, the metadata array contains:

- `size` (int) - File size in bytes
- `mtime` (int) - Last modification timestamp
- `permissions` (string) - Unix permissions (e.g., "0755")
- `is_readable` (bool) - Whether file is readable
- `is_writable` (bool) - Whether file is writable

**Methods:**

- `addChild(TreeNode $child): void` - Add a child node
- `split(string $path): ?TreeNode` - Extract a subtree
- `merge(TreeNode $other): TreeNode` - Merge with another node
- `append(TreeNode $child, ?string $childName = null): TreeNode` - Append a child node

#### `TreeBuilder`

[](#treebuilder)

**Final class** factory for building trees from paths.

**Methods:**

- `static fromPaths(array $paths, string $rootPath = 'src'): Tree` - Build a tree from array of paths

### Parsing

[](#parsing)

#### `TreeParser`

[](#treeparser)

**Final class** that parses string representations into tree structures.

**Methods:**

- `parse(string $tree): Tree` - Parse a tree string into a Tree object

### Printing

[](#printing)

#### `TreePrinter`

[](#treeprinter)

**Final class** that generates ASCII art representation of trees with extensive formatting and filtering options.

**Methods:**

- `print(TreeNode $tree, array $options = []): string` - Generate tree visualization

**Printer Options:**

*Filtering:*

- `show_hidden: bool` - Show/hide hidden files (default: true)
- `files_only: bool` - Show only files, exclude directories (default: false)
- `dirs_only: bool` - Show only directories, exclude files (default: false)
- `pattern: string` - Filter by shell-style pattern compatible with PHP `fnmatch` (e.g., '\*.php')
- `max_depth: int` - Limit tree depth (default: unlimited)

*Display:*

- `show_size: bool` - Show file sizes in human-readable format (default: false)
- `show_date: bool` - Show modification dates (default: false)
- `show_permissions: bool` - Show Unix permissions (default: false)

*Sorting:*

- `sort_by: string` - Sort by: 'name', 'size', 'date', 'type' (default: null = preserve order)
- `sort_order: string` - Sort order: 'asc', 'desc' (default: 'asc')

*Visual:*

- `colors: bool` - Use ANSI colors for terminal output (default: false)

**Example:**

```
$printer = new TreePrinter();

// Simple tree
echo $printer->print($tree);

// With icons and colors
echo $printer->print($tree, [
    'icons' => true,
    'colors' => true,
]);

// Show only PHP files with sizes, sorted by size
echo $printer->print($tree, [
    'pattern' => '*.php',
    'show_size' => true,
    'sort_by' => 'size',
    'sort_order' => 'desc',
]);

// Directories only with depth limit
echo $printer->print($tree, [
    'dirs_only' => true,
    'max_depth' => 2,
]);
```

### Traversal

[](#traversal)

#### `TreeTraverser`

[](#treetraverser)

**Final class** that traverses tree structures using the visitor pattern.

**Methods:**

- `addVisitor(VisitorInterface $visitor): self` - Add a visitor
- `traverse(TreeNode $node): void` - Traverse the tree

#### `CollectorVisitor`

[](#collectorvisitor)

**Final class** that collects files and directories during traversal.

**Methods:**

- `getFiles(): array` - Get collected file paths
- `getDirectories(): array` - Get collected directory paths
- `getTotalFiles(): int` - Get file count
- `getTotalDirectories(): int` - Get directory count
- `getSummary(): string` - Get formatted summary

#### `TreeFlattener`

[](#treeflattener)

**Final class** utility for flattening and rebuilding trees.

**Methods:**

- `static flatten(TreeNode $tree): array` - Flatten tree to paths array
- `static buildTree(array $paths, ?string $rootPath = null): Tree` - Build tree from paths

### Comparison

[](#comparison)

#### `TreeDiff`

[](#treediff)

**Final class** that compares two trees and identifies differences.

**Methods:**

- `static compare(TreeNode $oldTree, TreeNode $newTree): DiffResult` - Compare two trees

#### `DiffResult`

[](#diffresult)

**Readonly class** containing the results of a tree comparison.

**Methods:**

- `getAdded(): array` - Get nodes added in new tree
- `getRemoved(): array` - Get nodes removed from old tree
- `getUnchanged(): array` - Get nodes present in both trees
- `hasChanges(): bool` - Check if there are any changes
- `getSummary(): string` - Get compact summary (e.g., "+5 -3")
- `getDetailedSummary(): string` - Get detailed summary with counts

#### `DiffPrinter`

[](#diffprinter)

**Final class** that prints visual representations of tree differences.

**Methods:**

- `print(DiffResult $diff, array $options = []): string` - Print diff as tree with +/- markers
- `printSummary(DiffResult $diff): string` - Print detailed summary
- `printUnified(DiffResult $diff, string $oldLabel, string $newLabel): string` - Print unified diff format

Testing
-------

[](#testing)

Run the test suite:

```
composer test
```

Run static analysis:

```
composer phpstan
```

Run code style fixer:

```
composer cs-fix
```

Contributing
------------

[](#contributing)

Contributions are welcome! Please feel free to submit a Pull Request.

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

License
-------

[](#license)

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

###  Health Score

34

—

LowBetter than 75% of packages

Maintenance70

Regular maintenance activity

Popularity4

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 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

Unknown

Total

1

Last Release

168d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/a8951d49b371d210280a58ce48969a07d1f49924810f8a1fab3a9343eb46fdc9?d=identicon)[simonandre](/maintainers/simonandre)

---

Top Contributors

[![smnandre](https://avatars.githubusercontent.com/u/1359581?v=4)](https://github.com/smnandre "smnandre (3 commits)")

---

Tags

ascii-treedirectory-treefile-hierarchyfilesystemgit-filetreetree-difftree-parsertree-structurevisitor-patterntreetree-structurehierarchical-datadirectory-treefile-treetree-parsertree-printertree-traversal

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

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

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

###  Alternatives

[aliziodev/laravel-taxonomy

Laravel Taxonomy is a flexible and powerful package for managing taxonomies, categories, tags, and hierarchical structures in Laravel applications. Features nested-set support for optimal query performance on hierarchical data structures.

24426.4k](/packages/aliziodev-laravel-taxonomy)[baril/bonsai

An implementation of the Closure Tables pattern for Eloquent.

3596.2k](/packages/baril-bonsai)

PHPackages © 2026

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