Skip to content

Commit 484a6d0

Browse files
committed
Allow to create a tree from array
1 parent 067b62a commit 484a6d0

File tree

3 files changed

+104
-4
lines changed

3 files changed

+104
-4
lines changed

README.markdown

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ This is a Laravel 4 package for working with trees in a database.
22

33
__Contents:__
44

5-
- [Theory](#what-are-nested-sets?)
5+
- [Theory](#what-are-nested-sets)
66
- [Manipulating nodes](#manipulating-nodes)
77
- [Requirements](#requirements)
88
- [Installation](#installation)
@@ -19,6 +19,12 @@ a way to effectively store hierarchical data in a relational table. From wikiped
1919
> attributes. Querying becomes inexpensive: hierarchy membership can be tested by
2020
> comparing these numbers. Updating requires renumbering and is therefore expensive.
2121
22+
### Applications
23+
24+
NSM shows good performance when tree is updated rarely. It is tuned to be fast for
25+
getting related nodes. It'is ideally suited for building multi-depth menu or
26+
categories in shop.
27+
2228
Manipulating nodes
2329
------------------
2430

@@ -101,6 +107,9 @@ $node->parent()->associate($parent)->save();
101107
// #6 Using the parent attribute
102108
$node->parent_id = $parent->id;
103109
$node->save();
110+
111+
// #7 Using static method
112+
Category::create($attributes, $parent);
104113
```
105114

106115
And only a couple ways to prepend:
@@ -140,6 +149,30 @@ $bool = $node->up();
140149
$bool = $node->down(3);
141150
```
142151

152+
#### Building a tree from array
153+
154+
When using static method `create` on node, it checks whether attributes contains
155+
`children` key. If it does, it creates more nodes recursively.
156+
157+
```php
158+
$node = Category::create(
159+
[
160+
'name' => 'Foo',
161+
'children' =>
162+
[
163+
[
164+
'name' => 'Bar',
165+
'children' =>
166+
[
167+
[ 'name' => 'Baz' ],
168+
],
169+
],
170+
],
171+
]);
172+
```
173+
174+
`$node->children` now contains a list of created child nodes.
175+
143176
### Getting related nodes
144177

145178
In some cases we will use an `$id` variable which is an id of the target node.
@@ -210,6 +243,19 @@ $result = $node->getPrevSiblings();
210243
$result = $node->prevSiblings()->get();
211244
```
212245

246+
#### Getting related models from other table
247+
248+
Imagine that each category `has many` goods. I.e. `HasMany` relationship is established.
249+
How can you get all goods of all categories that are descendants of some node? Easy!
250+
251+
```php
252+
// Get ids of descendants
253+
$descendants = $node->descendants()->lists('id');
254+
255+
// Get goods
256+
$goods = Goods::whereIn('category_id', $descendants)->get();
257+
```
258+
213259
#### Manipulating a query
214260

215261
You have noticed that some methods return a query builder instance. It has some

src/Kalnoy/Nestedset/Node.php

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44

55
use Exception;
66
use LogicException;
7-
use \Illuminate\Database\Eloquent\Model as Eloquent;
8-
use \Illuminate\Database\Query\Builder;
9-
use \Illuminate\Database\Query\Expression;
7+
use Illuminate\Database\Eloquent\Model as Eloquent;
8+
use Illuminate\Database\Query\Builder;
9+
use Illuminate\Database\Query\Expression;
10+
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
1011

1112
class Node extends Eloquent {
1213

@@ -701,6 +702,37 @@ public function newFromBuilder($attributes = array())
701702
return $instance;
702703
}
703704

705+
/**
706+
* {@inheritdoc}
707+
*
708+
* Use `children` key on `$attributes` to create child nodes.
709+
*
710+
* @param \Kalnoy\Nestedset\Node $parent
711+
*
712+
*/
713+
public static function create(array $attributes, Node $parent = null)
714+
{
715+
$children = array_pull($attributes, 'children', []);
716+
717+
$instance = new static($attributes);
718+
719+
if ($parent) $instance->appendTo($parent);
720+
721+
$instance->save();
722+
723+
// Now create children
724+
$relation = new EloquentCollection;
725+
726+
foreach ($children as $child)
727+
{
728+
$relation->add($child = static::create($child, $instance));
729+
730+
$child->setRelation('parent', $instance);
731+
}
732+
733+
return $instance->setRelation('children', $relation);
734+
}
735+
704736
/**
705737
* Get node height (rgt - lft + 1).
706738
*

tests/NodeTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,4 +421,26 @@ public function testCountsTreeErrors()
421421

422422
$this->assertEquals([ 'oddness' => 0, 'duplicates' => 0, 'wrong_parent' => 0 ], $errors);
423423
}
424+
425+
public function testCreatesNode()
426+
{
427+
$node = Category::create([ 'name' => 'test' ]);
428+
429+
$this->assertEquals(19, $node->getLft());
430+
}
431+
432+
public function testCreatesTree()
433+
{
434+
$node = Category::create(
435+
[
436+
'name' => 'test',
437+
'children' =>
438+
[
439+
[ 'name' => 'test2' ],
440+
],
441+
]);
442+
443+
$this->assertTrue(isset($node->children));
444+
$this->assertCount(1, $node->children);
445+
}
424446
}

0 commit comments

Comments
 (0)