From 59c27e104be4cd7a09121e7842e79144d3a7abd2 Mon Sep 17 00:00:00 2001 From: Lito Date: Thu, 10 Mar 2022 17:00:56 +0100 Subject: [PATCH] [9.x] Added callable support to operatorForWhere on Collection (#41414) * [9.x] Added callable support to operatorForWhere on Collection Added `callable` support to `operatorForWhere`. Currently only Collection methods `where` and `whereFirst` are used without `callable` support. Adding callable to `operatorForWhere` allow complex usages as: ```php $city = $cities->firstWhere(fn ($city) => $city->state->available && ($city->state->id === $stateId)); ``` or ```php $state = $states->firstWhere(fn ($state) => (bool)$state->cities->firstWhere('id', $cityId)); ``` * Added callable test to `where` and `firstWhere` collection methods * Fixed firstWhere callable test typo --- .../Collections/Traits/EnumeratesValues.php | 10 +++++++--- tests/Support/SupportCollectionTest.php | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/Illuminate/Collections/Traits/EnumeratesValues.php b/src/Illuminate/Collections/Traits/EnumeratesValues.php index fec550211710..bf636c7ca790 100644 --- a/src/Illuminate/Collections/Traits/EnumeratesValues.php +++ b/src/Illuminate/Collections/Traits/EnumeratesValues.php @@ -311,7 +311,7 @@ public function every($key, $operator = null, $value = null) /** * Get the first item by the given key value pair. * - * @param string $key + * @param callable|string $key * @param mixed $operator * @param mixed $value * @return TValue|null @@ -548,7 +548,7 @@ public function unlessNotEmpty(callable $callback, callable $default = null) /** * Filter items by the given key value pair. * - * @param string $key + * @param callable|string $key * @param mixed $operator * @param mixed $value * @return static @@ -995,13 +995,17 @@ protected function getArrayableItems($items) /** * Get an operator checker callback. * - * @param string $key + * @param callable|string $key * @param string|null $operator * @param mixed $value * @return \Closure */ protected function operatorForWhere($key, $operator = null, $value = null) { + if (is_callable($key)) { + return $key; + } + if (func_num_args() === 1) { $value = true; diff --git a/tests/Support/SupportCollectionTest.php b/tests/Support/SupportCollectionTest.php index f8263ed78010..1c49205f8fa5 100755 --- a/tests/Support/SupportCollectionTest.php +++ b/tests/Support/SupportCollectionTest.php @@ -276,6 +276,11 @@ public function testFirstWhere($collection) $this->assertSame('gasket', $data->firstWhere('material', 'rubber')['type']); $this->assertNull($data->firstWhere('material', 'nonexistent')); $this->assertNull($data->firstWhere('nonexistent', 'key')); + + $this->assertSame('book', $data->firstWhere(fn ($value) => $value['material'] === 'paper')['type']); + $this->assertSame('gasket', $data->firstWhere(fn ($value) => $value['material'] === 'rubber')['type']); + $this->assertNull($data->firstWhere(fn ($value) => $value['material'] === 'nonexistent')); + $this->assertNull($data->firstWhere(fn ($value) => ($value['nonexistent'] ?? null) === 'key')); } /** @@ -1000,6 +1005,16 @@ public function testWhere($collection) $c->where('v', '>', $object)->values()->all() ); + $this->assertEquals( + [['v' => 3], ['v' => '3']], + $c->where(fn ($value) => $value['v'] == 3)->values()->all() + ); + + $this->assertEquals( + [['v' => 3]], + $c->where(fn ($value) => $value['v'] === 3)->values()->all() + ); + $c = new $collection([['v' => 1], ['v' => $object]]); $this->assertEquals( [['v' => $object]],