From 17dca9472ed115e270190ce2a21874673a99280c Mon Sep 17 00:00:00 2001 From: sfinktah Date: Tue, 2 Jul 2024 23:39:03 +1000 Subject: [PATCH] pluckMany dotted key support (#248) * added dotted tests for PluckMany * updated CHANGELOG * Update CHANGELOG.md --------- Co-authored-by: Freek Van der Herten --- src/Macros/PluckMany.php | 24 ++++++++++++++--------- tests/Macros/PluckManyTest.php | 36 ++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/src/Macros/PluckMany.php b/src/Macros/PluckMany.php index d7ea2ed..024c727 100644 --- a/src/Macros/PluckMany.php +++ b/src/Macros/PluckMany.php @@ -2,7 +2,6 @@ namespace Spatie\CollectionMacros\Macros; -use ArrayAccess; use Illuminate\Support\Arr; use Illuminate\Support\Collection; @@ -25,21 +24,28 @@ public function __invoke() return $this->map(function ($item) use ($keys) { if ($item instanceof Collection) { + if (Arr::accessible($item->all())) + return new static(pluckManyHelper($item->all(), $keys)); return $item->only($keys); } - if (is_array($item)) { - return Arr::only($item, $keys); + if (Arr::accessible($item)) { + return pluckManyHelper($item, $keys); } - if ($item instanceof ArrayAccess) { - return collect($keys)->mapWithKeys(function ($key) use ($item) { - return [$key => $item[$key]]; - })->toArray(); - } + // ArrayAccess handling not required, Arr::accessible includes it. - return (object) Arr::only(get_object_vars($item), $keys); + return (object) pluckManyHelper(get_object_vars($item), $keys); }); }; } } + +function pluckManyHelper($item, $keys): array { + $result = []; + foreach ($keys as $key) { + if (Arr::has($item, $key)) + $result[$key] = Arr::get($item, $key); + } + return $result; +} diff --git a/tests/Macros/PluckManyTest.php b/tests/Macros/PluckManyTest.php index 13f786b..0c6c606 100644 --- a/tests/Macros/PluckManyTest.php +++ b/tests/Macros/PluckManyTest.php @@ -40,3 +40,39 @@ ['name' => 'belle', 'hobby' => 'cross-stitch'], ]); }); + +it('can pluck dot-notated keys from a collection of collections', function () { + $data = Collection::make([ + collect(['id' => 1, 'name' => 'matt', 'info' => ['hobby' => 'coding']]), + collect(['id' => 2, 'name' => 'tomo', 'info' => ['hobby' => 'cooking']]), + ]); + + expect($data->pluckMany(['name', 'info.hobby']))->toEqual(collect([ + collect(['name' => 'matt', 'info.hobby' => 'coding']), + collect(['name' => 'tomo', 'info.hobby' => 'cooking']) + ])); +}); + +it('can pluck dot-notated keys from array and object items', function () { + $data = Collection::make([ + (object) ['id' => 1, 'name' => 'matt', 'info' => ['hobby' => 'coding']], + ['id' => 2, 'name' => 'tomo', 'info' => ['hobby' => 'cooking']], + ]); + + expect($data->pluckMany(['name', 'info.hobby'])->all())->toEqual([ + (object) ['name' => 'matt', 'info.hobby' => 'coding'], + ['name' => 'tomo', 'info.hobby' => 'cooking'], + ]); +}); + +it('can pluck dot-notated keys from objects that implement array access interface', function () { + $data = Collection::make([ + new TestArrayAccessImplementation(['id' => 1, 'name' => 'marco', 'info' => ['hobby' => 'drinking']]), + new TestArrayAccessImplementation(['id' => 2, 'name' => 'belle', 'info' => ['hobby' => 'cross-stitch']]), + ]); + + expect($data->pluckMany(['name', 'info.hobby'])->all())->toEqual([ + ['name' => 'marco', 'info.hobby' => 'drinking'], + ['name' => 'belle', 'info.hobby' => 'cross-stitch'], + ]); +});