66
77use ArgumentCountError ;
88use BadMethodCallException ;
9+ use Carbon \CarbonImmutable ;
910use Carbon \CarbonPeriod ;
1011use Closure ;
1112use DateTimeInterface ;
2526use MongoDB \Driver \Cursor ;
2627use Override ;
2728use RuntimeException ;
29+ use stdClass ;
2830
2931use function array_fill_keys ;
3032use function array_is_list ;
3941use function call_user_func_array ;
4042use function count ;
4143use function ctype_xdigit ;
44+ use function date_default_timezone_get ;
4245use function dd ;
4346use function dump ;
4447use function end ;
4548use function explode ;
4649use function func_get_args ;
4750use function func_num_args ;
4851use function get_debug_type ;
52+ use function get_object_vars ;
4953use function implode ;
5054use function in_array ;
5155use function is_array ;
5256use function is_bool ;
5357use function is_callable ;
5458use function is_float ;
5559use function is_int ;
60+ use function is_object ;
5661use function is_string ;
5762use function md5 ;
5863use function preg_match ;
@@ -227,7 +232,7 @@ public function hint($index)
227232 /** @inheritdoc */
228233 public function find ($ id , $ columns = [])
229234 {
230- return $ this ->where ('_id ' , '= ' , $ this ->convertKey ($ id ))->first ($ columns );
235+ return $ this ->where ('id ' , '= ' , $ this ->convertKey ($ id ))->first ($ columns );
231236 }
232237
233238 /** @inheritdoc */
@@ -391,7 +396,7 @@ public function toMql(): array
391396 }
392397
393398 $ options = [
394- 'typeMap ' => ['root ' => 'array ' , 'document ' => 'array ' ],
399+ 'typeMap ' => ['root ' => 'object ' , 'document ' => 'array ' ],
395400 ];
396401
397402 // Add custom query options
@@ -451,7 +456,7 @@ public function toMql(): array
451456 }
452457
453458 // Fix for legacy support, converts the results to arrays instead of objects.
454- $ options ['typeMap ' ] = ['root ' => 'array ' , 'document ' => 'array ' ];
459+ $ options ['typeMap ' ] = ['root ' => 'object ' , 'document ' => 'array ' ];
455460
456461 // Add custom query options
457462 if (count ($ this ->options )) {
@@ -506,7 +511,7 @@ public function getFresh($columns = [], $returnLazy = false)
506511 if ($ returnLazy ) {
507512 return LazyCollection::make (function () use ($ result ) {
508513 foreach ($ result as $ item ) {
509- yield $ this ->aliasIdForResult ($ item );
514+ yield is_object ( $ item ) ? $ this ->aliasIdForResult ($ item ) : $ item ;
510515 }
511516 });
512517 }
@@ -515,8 +520,8 @@ public function getFresh($columns = [], $returnLazy = false)
515520 $ result = $ result ->toArray ();
516521 }
517522
518- foreach ($ result as &$ document ) {
519- $ document = $ this ->aliasIdForResult ($ document ) ;
523+ foreach ($ result as &$ item ) {
524+ $ item = is_object ( $ item ) ? $ this ->aliasIdForResult ($ item ) : $ item ;
520525 }
521526
522527 return new Collection ($ result );
@@ -590,7 +595,7 @@ public function aggregate($function = null, $columns = ['*'])
590595 if (isset ($ results [0 ])) {
591596 $ result = (array ) $ results [0 ];
592597
593- return $ result ['aggregate ' ];
598+ return $ this -> aliasIdForResult ( $ result ['aggregate ' ]) ;
594599 }
595600 }
596601
@@ -628,6 +633,7 @@ public function orderBy($column, $direction = 'asc')
628633 }
629634
630635 $ column = (string ) $ column ;
636+ 631637 if ($ column === 'natural ' ) {
632638 $ this ->orders ['$natural ' ] = $ direction ;
633639 } else {
@@ -692,10 +698,9 @@ public function insert(array $values)
692698 if (isset ($ document ['_id ' ]) && $ document ['_id ' ] !== $ document ['id ' ]) {
693699 throw new InvalidArgumentException ('Cannot insert document with different "id" and "_id" values ' );
694700 }
695- 696- $ document ['_id ' ] = $ document ['id ' ];
697- unset($ document ['id ' ]);
698701 }
702+ 703+ $ document = $ this ->aliasIdForQuery ($ document );
699704 }
700705
701706 $ options = $ this ->inheritConnectionOptions ();
@@ -710,6 +715,8 @@ public function insertGetId(array $values, $sequence = null)
710715 {
711716 $ options = $ this ->inheritConnectionOptions ();
712717
718+ $ values = $ this ->aliasIdForQuery ($ values );
719+ 713720 $ result = $ this ->collection ->insertOne ($ values , $ options );
714721
715722 if (! $ result ->isAcknowledged ()) {
@@ -735,13 +742,6 @@ public function update(array $values, array $options = [])
735742 unset($ values [$ key ]);
736743 }
737744
738- // Since "id" is an alias for "_id", we prevent updating it
739- foreach ($ values as $ fields ) {
740- if (array_key_exists ('id ' , $ fields )) {
741- throw new InvalidArgumentException ('Cannot update "id" field. ' );
742- }
743- }
744- 745745 return $ this ->performUpdate ($ values , $ options );
746746 }
747747
@@ -778,9 +778,9 @@ public function pluck($column, $key = null)
778778 $ results = $ this ->get ($ key === null ? [$ column ] : [$ column , $ key ]);
779779
780780 // Convert ObjectID's to strings
781- if (((string ) $ key ) === '_id ' ) {
781+ if (((string ) $ key ) === 'id ' ) {
782782 $ results = $ results ->map (function ($ item ) {
783- $ item[ ' _id ' ] = (string ) $ item[ ' _id ' ] ;
783+ $ item-> id = (string ) $ item-> id ;
784784
785785 return $ item ;
786786 });
@@ -798,13 +798,14 @@ public function delete($id = null)
798798 // the ID to allow developers to simply and quickly remove a single row
799799 // from their database without manually specifying the where clauses.
800800 if ($ id !== null ) {
801- $ this ->where ('_id ' , '= ' , $ id );
801+ $ this ->where ('id ' , '= ' , $ id );
802802 }
803803
804804 $ wheres = $ this ->compileWheres ();
805805 $ options = $ this ->inheritConnectionOptions ();
806806
807- if (is_int ($ this ->limit )) {
807+ /** 1000 is a large value used by Laravel {@see DatabaseFailedJobProvider} */
808+ if (is_int ($ this ->limit ) && $ this ->limit !== 1000 ) {
808809 if ($ this ->limit !== 1 ) {
809810 throw new LogicException (sprintf ('Delete limit can be 1 or null (unlimited). Got %d ' , $ this ->limit ));
810811 }
@@ -997,15 +998,19 @@ protected function performUpdate(array $update, array $options = [])
997998 }
998999
9991000 // Since "id" is an alias for "_id", we prevent updating it
1000- foreach ($ update as $ operator => $ fields ) {
1001+ foreach ($ update as & $ fields ) {
10011002 if (array_key_exists ('id ' , $ fields )) {
10021003 throw new InvalidArgumentException ('Cannot update "id" field. ' );
10031004 }
1005+ 1006+ // Rename "id" to "_id" for embedded documents
1007+ $ fields = $ this ->aliasIdForQuery ($ fields );
10041008 }
10051009
10061010 $ options = $ this ->inheritConnectionOptions ($ options );
10071011
10081012 $ wheres = $ this ->compileWheres ();
1013+ 10091014 $ result = $ this ->collection ->updateMany ($ wheres , $ update , $ options );
10101015 if ($ result ->isAcknowledged ()) {
10111016 return $ result ->getModifiedCount () ? $ result ->getModifiedCount () : $ result ->getUpsertedCount ();
@@ -1188,7 +1193,7 @@ protected function compileWheres(): array
11881193 }
11891194 }
11901195
1191- return $ compiled ;
1196+ return $ this -> aliasIdForQuery ( $ compiled) ;
11921197 }
11931198
11941199 protected function compileWhereBasic (array $ where ): array
@@ -1561,13 +1566,52 @@ private function aliasIdForQuery(array $values): array
15611566 unset($ values ['id ' ]);
15621567 }
15631568
1569+ foreach ($ values as $ key => $ value ) {
1570+ if (is_string ($ key ) && str_ends_with ($ key , '.id ' )) {
1571+ $ values [substr ($ key , 0 , -3 ) . '._id ' ] = $ value ;
1572+ unset($ values [$ key ]);
1573+ }
1574+ }
1575+ 1576+ foreach ($ values as &$ value ) {
1577+ if ($ value instanceof DateTimeInterface) {
1578+ $ value = new UTCDateTime ($ value );
1579+ } elseif (is_array ($ value )) {
1580+ $ value = $ this ->aliasIdForQuery ($ value );
1581+ }
1582+ }
1583+ 15641584 return $ values ;
15651585 }
15661586
1567- private function aliasIdForResult (array $ values ): array
1587+ private function aliasIdForResult (stdClass | array $ values ): stdClass | array
15681588 {
1569- if (isset ($ values ['_id ' ])) {
1570- $ values ['id ' ] = $ values ['_id ' ];
1589+ if (is_array ($ values )) {
1590+ if (isset ($ values ['_id ' ])) {
1591+ $ values ['id ' ] = $ values ['_id ' ];
1592+ unset($ values ['_id ' ]);
1593+ }
1594+ 1595+ foreach ($ values as $ key => $ value ) {
1596+ if ($ value instanceof UTCDateTime) {
1597+ $ values [$ key ] = CarbonImmutable::createFromTimestamp ($ value ->toDateTime ()->getTimestamp (), 'UTC ' )->setTimezone (date_default_timezone_get ());
1598+ } elseif (is_array ($ value ) || $ value instanceof stdClass) {
1599+ $ values [$ key ] = $ this ->aliasIdForResult ($ value );
1600+ }
1601+ }
1602+ } else {
1603+ if (isset ($ values ->_id )) {
1604+ $ values ->id = $ values ->_id ;
1605+ unset($ values ->_id );
1606+ }
1607+ 1608+ foreach (get_object_vars ($ values ) as $ key => $ value ) {
1609+ if ($ value instanceof UTCDateTime) {
1610+ $ values ->{$ key } = CarbonImmutable::createFromTimestamp ($ value ->toDateTime ()->getTimestamp (), 'UTC ' )->setTimezone (date_default_timezone_get ());
1611+ } elseif (is_array ($ value ) || $ value instanceof stdClass) {
1612+ $ values ->{$ key } = $ this ->aliasIdForResult ($ value );
1613+ }
1614+ }
15711615 }
15721616
15731617 return $ values ;
0 commit comments