Skip to content

Commit

Permalink
Add max depth parameter for recursive macro (#240)
Browse files Browse the repository at this point in the history
* Allow max depth to be given to recursive method

* Create test

* Update test

* Adjust maxDepth param to be float

* Make params non-nullable

* Add information about max depth for recursive method in README

* Update test

* Add back try macro in README
  • Loading branch information
Kyzegs committed Mar 22, 2023
1 parent 1770c08 commit b1e2ec2
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 3 deletions.
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,40 @@ collect([
// subsequent arrays are now collections
```

In some cases you may not want to turn all the children into a collection. You can convert only to a certain depth by providing a number to the recursive method.

```php
collect([
'item' => [
'children' => [
'one' => [1],
'two' => [2]
]
]
])->recursive(1); // Collection(['item' => Collection(['children' => ['one' => [1], 'two' => [2]]])])
```

This can be useful when you know that at a certain depth it'll not be necessary or that it may break your code.

```php
collect([
'item' => [
'children' => [
'one' => [1],
'two' => [2]
]
]
])
->recursive(1)
->map(function ($item) {
return $item->map(function ($children) {
return $children->mapInto(Model::class);
});
}); // Collection(['item' => Collection(['children' => ['one' => Model(), 'two' => Model()]])])

// If we do not pass a max depth we will get the error "Argument #1 ($attributes) must be of type array"
```

### `rotate`

Rotate the items in the collection with given offset
Expand Down
13 changes: 10 additions & 3 deletions src/Macros/Recursive.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
/**
* Recursivly convert arrays and objects within a multi-dimensional array to Collections
*
* @param float $maxDepth
* @param int $depth
*
* @mixin \Illuminate\Support\Collection
*
* @return \Illuminate\Support\Collection
Expand All @@ -15,10 +18,14 @@ class Recursive
{
public function __invoke()
{
return function (): Collection {
return $this->map(function ($value) {
return function (float $maxDepth = INF, int $depth = 0): Collection {
return $this->map(function ($value) use ($depth, $maxDepth) {
if ($depth > $maxDepth) {
return $value;
}

if (is_array($value) || is_object($value)) {
return collect($value)->recursive();
return collect($value)->recursive($maxDepth, $depth + 1);
}

return $value;
Expand Down
17 changes: 17 additions & 0 deletions tests/Macros/RecursiveTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,21 @@ public function it_coverts_child_objects_to_collections()
$this->assertInstanceOf(Collection::class, $collection['child']);
$this->assertInstanceOf(Collection::class, $collection['child']['anotherchild']);
}

/** @test */
public function it_coverts_child_arrays_to_collections_with_a_max_depth()
{
$collection = Collection::make([
'child' => [
1, 2, 3, 'anotherchild' => [
1, 2, 3, 'lastchild' => [1, 2, 3]
],
],
])
->recursive(1);

$this->assertInstanceOf(Collection::class, $collection['child']);
$this->assertInstanceOf(Collection::class, $collection['child']['anotherchild']);
$this->assertIsArray($collection['child']['anotherchild']['lastchild']);
}
}

0 comments on commit b1e2ec2

Please sign in to comment.