richtjaku/arraynavigator

PHP Array Navigator

0.0.1 2025-05-10 13:03 UTC

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 navigationchild(), parent(), next(), prev() + higher‑level helpers like down() / up() and “closest” variants.
  • Sibling & ancestor inspection – Check availability with hasNext(), getPrevParent()
  • Searching & groupingfind(), findAll(), groupBy() with mini‑DSL for comparisons.
  • Sorting – Simple sortBy() utility for the current subtree.
  • Stateless static helperstreeStatic() & 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

MethodPurposeThrows on failure?
child($key)Move cursor into child keyInvalidArgumentException
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.