Skip to content

Commit 455a83f

Browse files
select and pluck method update
1 parent be757ec commit 455a83f

File tree

2 files changed

+79
-38
lines changed

2 files changed

+79
-38
lines changed

Collections/Traits/RelatedTrait.php

Lines changed: 64 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -673,37 +673,27 @@ public function select(...$keys)
673673
return new static($this->items);
674674
}
675675

676-
$lookup = array_fill_keys($keys, true);
677676
$selected = [];
678677

679-
foreach ($this->items as $index => $item) {
680-
if (is_array($item)) {
681-
// Intersect by keys for arrays
682-
$selected[$index] = array_intersect_key($item, $lookup);
683-
continue;
684-
}
678+
foreach ($this->items as $outerKey => $item) {
679+
$result = [];
685680

686-
if ($item instanceof \ArrayAccess) {
687-
// Build a filtered array from ArrayAccess
688-
$row = [];
689-
foreach ($keys as $k) {
690-
if ($item->offsetExists($k)) {
691-
$row[$k] = $item[$k];
681+
foreach ($keys as $key) {
682+
if (is_array($item)) {
683+
if (array_key_exists($key, $item)) {
684+
$result[$key] = $item[$key];
685+
}
686+
} elseif ($item instanceof \ArrayAccess) {
687+
$exists = method_exists($item, 'offsetExists') ? $item->offsetExists($key) : isset($item[$key]);
688+
if ($exists) {
689+
$result[$key] = $item[$key];
692690
}
691+
} elseif (is_object($item) && isset($item->{$key})) {
692+
$result[$key] = $item->{$key};
693693
}
694-
$selected[$index] = $row;
695-
continue;
696694
}
697695

698-
if (is_object($item)) {
699-
// Use public properties for plain objects
700-
$vars = get_object_vars($item);
701-
$selected[$index] = array_intersect_key($vars, $lookup);
702-
continue;
703-
}
704-
705-
// Fallback: return item unchanged
706-
$selected[$index] = $item;
696+
$selected[$outerKey] = $result;
707697
}
708698

709699
return new static($selected);
@@ -753,20 +743,64 @@ public function mapWithKeys(callable $callback)
753743
}
754744

755745
/**
756-
* Pluck a specific field from each item in the collection.
746+
* Get the values of a given key.
757747
*
758-
* @param string|array $key
748+
* @param string|int|array<array-key, string> $value
749+
* @param string|null $key
759750
* @return static
760751
*/
761-
public function pluck(...$key)
752+
public function pluck($value, $key = null)
762753
{
763754
$results = [];
764755

765-
$key = Str::flatten($key);
756+
// Resolve nested values from arrays/ArrayAccess/objects.
757+
// - $path may be a string (supports dot notation), int, or array of segments
758+
$resolve = function ($target, $path) {
759+
if (is_array($path)) {
760+
$segments = $path;
761+
} elseif (is_string($path)) {
762+
// Support dot notation transparently
763+
$segments = explode('.', $path);
764+
} else {
765+
$segments = [$path];
766+
}
767+
768+
$current = $target;
769+
770+
foreach ($segments as $segment) {
771+
if (is_array($current) || $current instanceof \ArrayAccess) {
772+
// Avoid illegal offset types
773+
if (!is_int($segment) && !is_string($segment)) {
774+
return null;
775+
}
776+
777+
if (is_array($current)) {
778+
$current = array_key_exists($segment, $current) ? $current[$segment] : null;
779+
} else { // ArrayAccess
780+
$current = isset($current[$segment]) ? $current[$segment] : null;
781+
}
782+
} elseif (is_object($current)) {
783+
$current = $current->$segment ?? null;
784+
} else {
785+
return null;
786+
}
787+
788+
if ($current === null) {
789+
break;
790+
}
791+
}
792+
793+
return $current;
794+
};
766795

767796
foreach ($this->items as $item) {
768-
if (is_array($item) || $item instanceof \ArrayAccess) {
769-
$results[] = is_array($key) ? array_intersect_key($item, array_flip((array) $key)) : ($item[$key] ?? null);
797+
$itemValue = $resolve($item, $value);
798+
$itemKey = $key !== null ? $resolve($item, $key) : null;
799+
800+
if ($key !== null && $itemKey !== null) {
801+
$results[$itemKey] = $itemValue;
802+
} else {
803+
$results[] = $itemValue;
770804
}
771805
}
772806

Tests/collection.php

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,32 @@
1414
['id' => 5, 'name' => 'Emily', 'age' => 25],
1515
];
1616

17-
$language = [
17+
$language = tcollect([
1818
'en' => [
1919
'lang_name' => 'English',
2020
'flag' => 'us',
2121
'locale_iso' => 'en',
2222
'locale' => 'en',
23-
'locale_allow' => 'true'
23+
'locale_allow' => 'true',
24+
'speakers' => [
25+
'first_day' => ['Rosa', 'Judith'],
26+
]
2427
],
2528
'cn' => [
2629
'lang_name' => '中文',
2730
'flag' => 'hk',
2831
'locale_iso' => 'cn',
2932
'locale' => 'zh-Hant',
30-
'locale_allow' => 'true'
33+
'locale_allow' => 'true',
34+
'speakers' => [
35+
'first_day' => ['Abigail', 'Joey'],
36+
],
3137
]
32-
];
38+
]);
3339

3440

3541
dump(
36-
tcollect($language)
42+
$language
3743
->filter(fn($value) => $value['locale_allow'] == 'true')
3844
->mapWithKeys(fn ($value) => [
3945
$value['locale_iso'] => [
@@ -149,14 +155,15 @@
149155
// pluck()
150156
dump(
151157
'pluck',
152-
$collection->pluck(['name', 'age'])
153-
// ['John', 'Jane', 'Doe', 'Smith', 'Emily']
158+
$language->pluck('lang_name', 'locale')->all(), // ["en" => "English", "zh-Hant" => "中文"]
159+
// $language->pluck('speakers.first_day', 'flag')->all(),
160+
// $collection->pluck('name', 'age'),
154161
);
155162

156163
// select()
157164
dump(
158165
'select[name, age] and pluck(age)',
159-
$collection->select(['name', 'age'])->pluck('age')
166+
$collection->select(['name', 'age'])->all()
160167
);
161168

162169
// search()

0 commit comments

Comments
 (0)