From 6d39a2da6628385cf5e2a39ef0a2a07cd1f7e390 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Sat, 16 Aug 2025 23:50:14 +0800 Subject: [PATCH 1/2] Add Arr::push() method for pushing items into arrays using dot notation - Add push method to ArrMixin for pushing values to array paths - Add corresponding output method to Arr class - Add comprehensive tests covering various use cases - Support both dot notation keys and root level pushing --- src/macros/output/Hyperf/Collection/Arr.php | 8 +++++++ src/macros/src/ArrMixin.php | 11 ++++++++++ tests/Macros/ArrTest.php | 24 +++++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/src/macros/output/Hyperf/Collection/Arr.php b/src/macros/output/Hyperf/Collection/Arr.php index d04d3778c..eed542462 100644 --- a/src/macros/output/Hyperf/Collection/Arr.php +++ b/src/macros/output/Hyperf/Collection/Arr.php @@ -99,6 +99,14 @@ public static function integer(ArrayAccess|array $array, string|int|null $key, ? { } + /** + * Push an item into an array using "dot" notation. + * @return array + */ + public static function push(ArrayAccess|array &$array, string|int|null $key, mixed ...$values) + { + } + /** * Get a string item from an array using "dot" notation. * @return string diff --git a/src/macros/src/ArrMixin.php b/src/macros/src/ArrMixin.php index 005b048df..006992348 100644 --- a/src/macros/src/ArrMixin.php +++ b/src/macros/src/ArrMixin.php @@ -217,4 +217,15 @@ public function sortByMany() return $array; }; } + + public function push() + { + return function (ArrayAccess|array &$array, string|int|null $key, mixed ...$values) { + $target = Arr::array($array, $key, []); // @phpstan-ignore staticMethod.notFound + + array_push($target, ...$values); + + return Arr::set($array, $key, $target); // @phpstan-ignore staticMethod.notFound + }; + } } diff --git a/tests/Macros/ArrTest.php b/tests/Macros/ArrTest.php index 303f8b5ef..0ef69cace 100644 --- a/tests/Macros/ArrTest.php +++ b/tests/Macros/ArrTest.php @@ -242,3 +242,27 @@ function ($a, $b) { $this->assertTrue(Arr::some(['foo', 2], fn ($value, $key) => is_string($value))); $this->assertTrue(Arr::some(['foo', 'bar'], fn ($value, $key) => is_string($value))); }); + +test('test push', function () { + $array = []; + + Arr::push($array, 'office.furniture', 'Desk'); + $this->assertEquals(['Desk'], $array['office']['furniture']); + + Arr::push($array, 'office.furniture', 'Chair', 'Lamp'); + $this->assertEquals(['Desk', 'Chair', 'Lamp'], $array['office']['furniture']); + + $array = []; + + Arr::push($array, null, 'Chris', 'Nuno'); + $this->assertEquals(['Chris', 'Nuno'], $array); + + Arr::push($array, null, 'Taylor'); + $this->assertEquals(['Chris', 'Nuno', 'Taylor'], $array); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Array value for key [foo.bar] must be an array, boolean found.'); + + $array = ['foo' => ['bar' => false]]; + Arr::push($array, 'foo.bar', 'baz'); +}); From 56de18075f5e6616eff6f2a997178ebbc04601fb Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Sun, 17 Aug 2025 00:56:36 +0800 Subject: [PATCH 2/2] feat: add Arr::push() method for array manipulation with dot notation - Add Arr::push() method to ArrMixin for pushing values to arrays using dot notation - Support both nested array paths and root-level array pushing - Include comprehensive test coverage for various scenarios - Handle type validation with clear error messages - Return new array instead of modifying by reference to work with macro system The method allows pushing values to arrays at any depth using dot notation, similar to Arr::set() but specifically for array appending operations. --- src/macros/output/Hyperf/Collection/Arr.php | 2 +- src/macros/src/ArrMixin.php | 26 +++++++++++++++++---- tests/Macros/ArrTest.php | 12 ++++++---- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/macros/output/Hyperf/Collection/Arr.php b/src/macros/output/Hyperf/Collection/Arr.php index eed542462..c32da9bb0 100644 --- a/src/macros/output/Hyperf/Collection/Arr.php +++ b/src/macros/output/Hyperf/Collection/Arr.php @@ -103,7 +103,7 @@ public static function integer(ArrayAccess|array $array, string|int|null $key, ? * Push an item into an array using "dot" notation. * @return array */ - public static function push(ArrayAccess|array &$array, string|int|null $key, mixed ...$values) + public static function push(array $array, string|int|null $key, mixed ...$values) { } diff --git a/src/macros/src/ArrMixin.php b/src/macros/src/ArrMixin.php index 006992348..4f331b84b 100644 --- a/src/macros/src/ArrMixin.php +++ b/src/macros/src/ArrMixin.php @@ -220,12 +220,28 @@ public function sortByMany() public function push() { - return function (ArrayAccess|array &$array, string|int|null $key, mixed ...$values) { - $target = Arr::array($array, $key, []); // @phpstan-ignore staticMethod.notFound - - array_push($target, ...$values); + return function (array $array, string|int|null $key, mixed ...$values) { + if ($key === null) { + foreach ($values as $value) { + $array[] = $value; + } + return $array; + } - return Arr::set($array, $key, $target); // @phpstan-ignore staticMethod.notFound + $current = Arr::get($array, $key, []); + + if (!is_array($current)) { + throw new InvalidArgumentException( + sprintf('Array value for key [%s] must be an array, %s found.', $key, gettype($current)) + ); + } + + $merged = array_merge($current, $values); + + $result = $array; + Arr::set($result, $key, $merged); + + return $result; }; } } diff --git a/tests/Macros/ArrTest.php b/tests/Macros/ArrTest.php index 0ef69cace..72d7fcd07 100644 --- a/tests/Macros/ArrTest.php +++ b/tests/Macros/ArrTest.php @@ -8,8 +8,12 @@ * @document https://github.com/friendsofhyperf/components/blob/main/README.md * @contact huangdijia@gmail.com */ +use FriendsOfHyperf\Macros\ArrMixin; use Hyperf\Collection\Arr; +// Register the mixin for tests +Arr::mixin(new ArrMixin()); + require_once __DIR__ . '/Stubs/Common.php'; test('test arrayable', function () { @@ -246,18 +250,18 @@ function ($a, $b) { test('test push', function () { $array = []; - Arr::push($array, 'office.furniture', 'Desk'); + $array = Arr::push($array, 'office.furniture', 'Desk'); $this->assertEquals(['Desk'], $array['office']['furniture']); - Arr::push($array, 'office.furniture', 'Chair', 'Lamp'); + $array = Arr::push($array, 'office.furniture', 'Chair', 'Lamp'); $this->assertEquals(['Desk', 'Chair', 'Lamp'], $array['office']['furniture']); $array = []; - Arr::push($array, null, 'Chris', 'Nuno'); + $array = Arr::push($array, null, 'Chris', 'Nuno'); $this->assertEquals(['Chris', 'Nuno'], $array); - Arr::push($array, null, 'Taylor'); + $array = Arr::push($array, null, 'Taylor'); $this->assertEquals(['Chris', 'Nuno', 'Taylor'], $array); $this->expectException(InvalidArgumentException::class);