richtjaku / arraynavigator
PHP Array Navigator
Requires
- php: >= 8.1
Requires (Dev)
- nette/tester: ^2.5
This package is not auto-updated.
Last update: 2025-06-22 10:12:37 UTC
README
ArrayNavigator
is a tiny zero‑dependency PHP helper that lets you treat any PHP array as a navigable tree.
Give it either a flat record set (id
/parent
) or an already nested structure and it will build a fully‑featured in‑memory tree that you can walk, query, and rearrange with an intuitive API.
Why? When you already have all data in memory (e.g. pre‑loaded categories, menu items, ACLs …) you often need to move a cursor around, see siblings, dive into children, or find neighbours of ancestors. Doing that by hand quickly turns into spaghetti;
ArrayNavigator
keeps it pleasant.
Features
- Automatic tree building – Accepts both flat (
id/parent
) and nested input. - Cursor‑based navigation –
child()
,parent()
,next()
,prev()
+ higher‑level helpers likedown()
/up()
and “closest” variants. - Sibling & ancestor inspection – Check availability with
hasNext()
,getPrevParent()
… - Searching & grouping –
find()
,findAll()
,groupBy()
with mini‑DSL for comparisons. - Sorting – Simple
sortBy()
utility for the current subtree. - Stateless static helpers –
treeStatic()
&groupByStatic()
reusable outside the class. - 100 % PHP 8.1, strict types, no external dependencies (only auto‑detects Nette\Database\Table\ActiveRow via
toArray()
when present).
Requirements
- PHP 8.1 or newer (uses enum‑like
match
, union types, etc.)
No extensions beyond standard library are necessary.
Installation
Install via Composer from Packagist:
composer require richtjaku/arraynavigator
—or—
If you prefer manual installation, drop ArrayNavigator.php
into your codebase and add a PSR‑4 autoload mapping:
"autoload": {
"psr-4": {
"Richtjaku\\": "src/"
}
}
Quick‑start example
<?php
use Richtjaku\ArrayNavigator;
$records = [
['id' => 1, 'parent' => null, 'name' => 'Root'],
['id' => 2, 'parent' => 1, 'name' => 'Child A'],
['id' => 3, 'parent' => 1, 'name' => 'Child B'],
['id' => 4, 'parent' => 2, 'name' => 'Grandchild'],
];
$nav = new ArrayNavigator($records); // ← automatic flat → tree conversion
$nav->child(0); // jump to first root node (index 0)
$nav->down(); // go to its first child (Child A)
echo $nav->current()['name']; // ➜ "Child A"
// Peek ahead without moving the cursor
$next = $nav->getNext(); // record of "Child B"
// Find by arbitrary conditions (mini‑DSL)
$grand = $nav->find(['name' => 'Grandchild']);
// Reset back to the top
$nav->reset();
Navigation cheatsheet
Method | Purpose | Throws on failure? |
---|---|---|
child($key) | Move cursor into child key | ✔ InvalidArgumentException |
parent() | Move one level up | ✔ |
next() / prev() | Move to next/previous sibling | ✔ |
down() / up() | DFS preorder logical next/previous | ✔ |
nextParent() / prevParent() | Move among parent’s siblings | ✔ |
closestNextParent() / closestPrevParent() | First ancestor that has a sibling in given direction | ✔ |
reset() | Jump back to root | – |
Helper peekers (do not move the cursor):
hasNext()
,hasPrev()
/hasNextParent()
,hasPrevParent()
getNext()
,getPrev()
/getNextParent()
,getPrevParent()
getUp()
,getDown()
Query helpers
// Searches are confined to the *current* subtree
$conditions = [
'name' => 'My Node', // equality
'order' => '>=10', // operators: =, !=, <, >, <=, >=
'type' => ['operator' => 'in', 'value' => ['folder','file']],
];
$first = $nav->find($conditions); // first matching record or null
$all = $nav->findAll($conditions); // array|null
$key = $nav->findKey($conditions); // first matching key or null
$keys = $nav->findAllKeys($conditions);
sortBy($field, $desc = true)
and groupBy($field, $returnRest = false)
also operate on the current subtree.
Error handling
All navigation methods throw \InvalidArgumentException
when the requested move is impossible (e.g. "already at the first root", "no next sibling…"). You can catch and ignore them or use the corresponding has*/get*
helpers to probe safely beforehand.
Static helpers
If you only need to build a nested tree without maintaining a cursor, ArrayNavigator
exposes its algorithms as static methods as well:
$tree = ArrayNavigator::treeStatic($records); // flat → nested
$groups = ArrayNavigator::groupByStatic($records, 'category'); // grouping
Both functions accept the same optional parameters as their instance counterparts (idKey
, parentKey
, childrenKey
, …).
Contributing & License
PRs and issues are welcome! The code is released under the MIT License – see LICENSE
for details.