Skip to content

Commit 6cefe7a

Browse files
authored
Merge pull request lazychaser#200 from ralphschindler/ancestors-relation-cleanup
Updates to Ancestor Relation
2 parents 39d5e83 + b28f136 commit 6cefe7a

File tree

4 files changed

+85
-3
lines changed

4 files changed

+85
-3
lines changed

README.markdown

+13
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ Node has following relationships that are fully functional and can be eagerly lo
5757

5858
- Node belongs to `parent`
5959
- Node has many `children`
60+
- Node has many `ancestors`
6061
- Node has many `descendants`
6162

6263
### Inserting nodes
@@ -232,6 +233,18 @@ $result = $node->ancestors()->get();
232233
$result = Category::ancestorsOf($id);
233234
```
234235

236+
A collection of ancestors can be eagerly loaded:
237+
238+
```php
239+
$categories = Category::with('ancestors')->paginate(30);
240+
241+
// in view for breadcrumbs:
242+
@foreach($categories as $i => $category)
243+
<small>{{ $category->ancestors->count() ? implode(' > ', $category->ancestors->pluck('name')->toArray()) : 'Top Level' }}</small><br>
244+
{{ $category->name }}
245+
@endforeach
246+
```
247+
235248
#### Descendants
236249

237250
Descendants are all nodes in a sub tree, i.e. children of node, children of

src/AncestorsRelation.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ public function addEagerConstraints(array $models)
137137
$this->query->whereNested(function (Builder $inner) use ($sql) {
138138
$inner->whereRaw($sql);
139139
});
140-
$this->query->orderBy('lft', 'ASC');
140+
$this->query->orderBy($this->parent->getLftName(), 'ASC');
141141
}
142142

143143
/**

src/NodeTrait.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -341,9 +341,9 @@ public function prevNodes()
341341
}
342342

343343
/**
344-
* Get query for ancestors to the node not including the node itself.
344+
* Get query ancestors of the node.
345345
*
346-
* @return QueryBuilder
346+
* @return AncestorsRelation
347347
*/
348348
public function ancestors()
349349
{

tests/NodeTest.php

+69
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,75 @@ public function testWhereIsLeaf()
860860

861861
$this->assertFalse($category->isLeaf());
862862
}
863+
864+
public function testEagerLoadAncestors()
865+
{
866+
$queryLogCount = count(Capsule::connection()->getQueryLog());
867+
$categories = Category::with('ancestors')->orderBy('name')->get();
868+
869+
$this->assertEquals($queryLogCount + 2, count(Capsule::connection()->getQueryLog()));
870+
871+
$expectedShape = [
872+
'apple (3)}' => 'store (1) > notebooks (2)',
873+
'galaxy (8)}' => 'store (1) > mobile (5) > samsung (7)',
874+
'lenovo (4)}' => 'store (1) > notebooks (2)',
875+
'lenovo (10)}' => 'store (1) > mobile (5)',
876+
'mobile (5)}' => 'store (1)',
877+
'nokia (6)}' => 'store (1) > mobile (5)',
878+
'notebooks (2)}' => 'store (1)',
879+
'samsung (7)}' => 'store (1) > mobile (5)',
880+
'sony (9)}' => 'store (1) > mobile (5)',
881+
'store (1)}' => '',
882+
'store_2 (11)}' => ''
883+
];
884+
885+
$output = [];
886+
887+
foreach ($categories as $category) {
888+
$output["{$category->name} ({$category->id})}"] = $category->ancestors->count()
889+
? implode(' > ', $category->ancestors->map(function ($cat) { return "{$cat->name} ({$cat->id})"; })->toArray())
890+
: '';
891+
}
892+
893+
$this->assertEquals($expectedShape, $output);
894+
}
895+
896+
public function testLazyLoadAncestors()
897+
{
898+
$queryLogCount = count(Capsule::connection()->getQueryLog());
899+
$categories = Category::orderBy('name')->get();
900+
901+
$this->assertEquals($queryLogCount + 1, count(Capsule::connection()->getQueryLog()));
902+
903+
$expectedShape = [
904+
'apple (3)}' => 'store (1) > notebooks (2)',
905+
'galaxy (8)}' => 'store (1) > mobile (5) > samsung (7)',
906+
'lenovo (4)}' => 'store (1) > notebooks (2)',
907+
'lenovo (10)}' => 'store (1) > mobile (5)',
908+
'mobile (5)}' => 'store (1)',
909+
'nokia (6)}' => 'store (1) > mobile (5)',
910+
'notebooks (2)}' => 'store (1)',
911+
'samsung (7)}' => 'store (1) > mobile (5)',
912+
'sony (9)}' => 'store (1) > mobile (5)',
913+
'store (1)}' => '',
914+
'store_2 (11)}' => ''
915+
];
916+
917+
$output = [];
918+
919+
foreach ($categories as $category) {
920+
$output["{$category->name} ({$category->id})}"] = $category->ancestors->count()
921+
? implode(' > ', $category->ancestors->map(function ($cat) { return "{$cat->name} ({$cat->id})"; })->toArray())
922+
: '';
923+
}
924+
925+
// assert that there is number of original query + 1 + number of rows to fulfill the relation
926+
$this->assertEquals($queryLogCount + 12, count(Capsule::connection()->getQueryLog()));
927+
928+
$this->assertEquals($expectedShape, $output);
929+
}
930+
931+
863932
}
864933

865934
function all($items)

0 commit comments

Comments
 (0)