diff --git a/README.markdown b/README.markdown index 27d948b..c345767 100644 --- a/README.markdown +++ b/README.markdown @@ -417,6 +417,16 @@ This will output something like this: - Another root ``` +##### Building flat tree + +Also, you can build a flat tree: a list of nodes where child nodes are immediately +after parent node. This is helpful when you get nodes with custom order +(i.e. alphabetically) and don't want to use recursion to iterate over your nodes. + +```php +$nodes = Category::get()->toFlatTree(); +``` + ##### Getting a subtree Sometimes you don't need whole tree to be loaded and just some subtree of specific node. diff --git a/src/Collection.php b/src/Collection.php index 312a2b5..2dd26df 100644 --- a/src/Collection.php +++ b/src/Collection.php @@ -77,7 +77,7 @@ public function toTree($root = false) * * @return int */ - protected function getRootNodeId($root) + protected function getRootNodeId($root = false) { if (NestedSet::isNode($root)) { return $root->getKey(); @@ -106,44 +106,38 @@ protected function getRootNodeId($root) * Build a list of nodes that retain the order that they were pulled from * the database. * - * @return Collection|static + * @param bool $root + * + * @return static */ - public function toFlattenedTree() + public function toFlatTree($root = false) { - $tree = $this->toTree(); + $result = new static; - return $tree->flattenTree(); - } + if ($this->isEmpty()) return $result; - /** - * Flatten a tree into a non recursive array - */ - public function flattenTree() - { - $items = []; - - foreach ($this->items as $node) { - $items = array_merge($items, $this->flattenNode($node)); - } + $groupedNodes = $this->groupBy($this->first()->getParentIdName()); - return new static($items); + return $result->flattenTree($groupedNodes, $this->getRootNodeId($root)); } /** - * Flatten a single node + * Flatten a tree into a non recursive array. + * + * @param Collection $groupedNodes + * @param mixed $parentId * - * @param $node - * @return array + * @return $this */ - protected function flattenNode($node) + protected function flattenTree(self $groupedNodes, $parentId) { - $items = []; - $items[] = $node; + foreach ($groupedNodes->get($parentId, []) as $node) { + $this->push($node); - foreach ($node->children as $childNode) { - $items = array_merge($items, $this->flattenNode($childNode)); + $this->flattenTree($groupedNodes, $node->getKey()); } - return $items; + return $this; } + } \ No newline at end of file diff --git a/tests/NodeTest.php b/tests/NodeTest.php index c731c95..ccd55c5 100644 --- a/tests/NodeTest.php +++ b/tests/NodeTest.php @@ -806,6 +806,16 @@ public function testRebuildFailsWithInvalidPK() { Category::rebuildTree([ [ 'id' => 24 ] ]); } + + public function testFlatTree() + { + $node = $this->findCategory('mobile'); + $tree = $node->descendants()->orderBy('name')->get()->toFlatTree(); + + $this->assertCount(5, $tree); + $this->assertEquals('samsung', $tree[2]->name); + $this->assertEquals('galaxy', $tree[3]->name); + } } function all($items)