@@ -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
0 commit comments