6
6
7
7
use ArgumentCountError ;
8
8
use BadMethodCallException ;
9
+ use Carbon \CarbonImmutable ;
9
10
use Carbon \CarbonPeriod ;
10
11
use Closure ;
11
12
use DateTimeInterface ;
25
26
use MongoDB \Driver \Cursor ;
26
27
use Override ;
27
28
use RuntimeException ;
29
+ use stdClass ;
28
30
29
31
use function array_fill_keys ;
30
32
use function array_is_list ;
39
41
use function call_user_func_array ;
40
42
use function count ;
41
43
use function ctype_xdigit ;
44
+ use function date_default_timezone_get ;
42
45
use function dd ;
43
46
use function dump ;
44
47
use function end ;
45
48
use function explode ;
46
49
use function func_get_args ;
47
50
use function func_num_args ;
48
51
use function get_debug_type ;
52
+ use function get_object_vars ;
49
53
use function implode ;
50
54
use function in_array ;
51
55
use function is_array ;
52
56
use function is_bool ;
53
57
use function is_callable ;
54
58
use function is_float ;
55
59
use function is_int ;
60
+ use function is_object ;
56
61
use function is_string ;
57
62
use function md5 ;
58
63
use function preg_match ;
@@ -227,7 +232,7 @@ public function hint($index)
227
232
/** @inheritdoc */
228
233
public function find ($ id , $ columns = [])
229
234
{
230
- return $ this ->where ('_id ' , '= ' , $ this ->convertKey ($ id ))->first ($ columns );
235
+ return $ this ->where ('id ' , '= ' , $ this ->convertKey ($ id ))->first ($ columns );
231
236
}
232
237
233
238
/** @inheritdoc */
@@ -391,7 +396,7 @@ public function toMql(): array
391
396
}
392
397
393
398
$ options = [
394
- 'typeMap ' => ['root ' => 'array ' , 'document ' => 'array ' ],
399
+ 'typeMap ' => ['root ' => 'object ' , 'document ' => 'array ' ],
395
400
];
396
401
397
402
// Add custom query options
@@ -451,7 +456,7 @@ public function toMql(): array
451
456
}
452
457
453
458
// 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 ' ];
455
460
456
461
// Add custom query options
457
462
if (count ($ this ->options )) {
@@ -506,7 +511,7 @@ public function getFresh($columns = [], $returnLazy = false)
506
511
if ($ returnLazy ) {
507
512
return LazyCollection::make (function () use ($ result ) {
508
513
foreach ($ result as $ item ) {
509
- yield $ this ->aliasIdForResult ($ item );
514
+ yield is_object ( $ item ) ? $ this ->aliasIdForResult ($ item ) : $ item ;
510
515
}
511
516
});
512
517
}
@@ -515,8 +520,8 @@ public function getFresh($columns = [], $returnLazy = false)
515
520
$ result = $ result ->toArray ();
516
521
}
517
522
518
- foreach ($ result as &$ document ) {
519
- $ document = $ this ->aliasIdForResult ($ document ) ;
523
+ foreach ($ result as &$ item ) {
524
+ $ item = is_object ( $ item ) ? $ this ->aliasIdForResult ($ item ) : $ item ;
520
525
}
521
526
522
527
return new Collection ($ result );
@@ -590,7 +595,7 @@ public function aggregate($function = null, $columns = ['*'])
590
595
if (isset ($ results [0 ])) {
591
596
$ result = (array ) $ results [0 ];
592
597
593
- return $ result ['aggregate ' ];
598
+ return $ this -> aliasIdForResult ( $ result ['aggregate ' ]) ;
594
599
}
595
600
}
596
601
@@ -628,6 +633,7 @@ public function orderBy($column, $direction = 'asc')
628
633
}
629
634
630
635
$ column = (string ) $ column ;
636
+
631
637
if ($ column === 'natural ' ) {
632
638
$ this ->orders ['$natural ' ] = $ direction ;
633
639
} else {
@@ -692,10 +698,9 @@ public function insert(array $values)
692
698
if (isset ($ document ['_id ' ]) && $ document ['_id ' ] !== $ document ['id ' ]) {
693
699
throw new InvalidArgumentException ('Cannot insert document with different "id" and "_id" values ' );
694
700
}
695
-
696
- $ document ['_id ' ] = $ document ['id ' ];
697
- unset($ document ['id ' ]);
698
701
}
702
+
703
+ $ document = $ this ->aliasIdForQuery ($ document );
699
704
}
700
705
701
706
$ options = $ this ->inheritConnectionOptions ();
@@ -710,6 +715,8 @@ public function insertGetId(array $values, $sequence = null)
710
715
{
711
716
$ options = $ this ->inheritConnectionOptions ();
712
717
718
+ $ values = $ this ->aliasIdForQuery ($ values );
719
+
713
720
$ result = $ this ->collection ->insertOne ($ values , $ options );
714
721
715
722
if (! $ result ->isAcknowledged ()) {
@@ -735,13 +742,6 @@ public function update(array $values, array $options = [])
735
742
unset($ values [$ key ]);
736
743
}
737
744
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
-
745
745
return $ this ->performUpdate ($ values , $ options );
746
746
}
747
747
@@ -778,9 +778,9 @@ public function pluck($column, $key = null)
778
778
$ results = $ this ->get ($ key === null ? [$ column ] : [$ column , $ key ]);
779
779
780
780
// Convert ObjectID's to strings
781
- if (((string ) $ key ) === '_id ' ) {
781
+ if (((string ) $ key ) === 'id ' ) {
782
782
$ results = $ results ->map (function ($ item ) {
783
- $ item[ ' _id ' ] = (string ) $ item[ ' _id ' ] ;
783
+ $ item-> id = (string ) $ item-> id ;
784
784
785
785
return $ item ;
786
786
});
@@ -798,13 +798,14 @@ public function delete($id = null)
798
798
// the ID to allow developers to simply and quickly remove a single row
799
799
// from their database without manually specifying the where clauses.
800
800
if ($ id !== null ) {
801
- $ this ->where ('_id ' , '= ' , $ id );
801
+ $ this ->where ('id ' , '= ' , $ id );
802
802
}
803
803
804
804
$ wheres = $ this ->compileWheres ();
805
805
$ options = $ this ->inheritConnectionOptions ();
806
806
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 ) {
808
809
if ($ this ->limit !== 1 ) {
809
810
throw new LogicException (sprintf ('Delete limit can be 1 or null (unlimited). Got %d ' , $ this ->limit ));
810
811
}
@@ -997,15 +998,19 @@ protected function performUpdate(array $update, array $options = [])
997
998
}
998
999
999
1000
// Since "id" is an alias for "_id", we prevent updating it
1000
- foreach ($ update as $ operator => $ fields ) {
1001
+ foreach ($ update as & $ fields ) {
1001
1002
if (array_key_exists ('id ' , $ fields )) {
1002
1003
throw new InvalidArgumentException ('Cannot update "id" field. ' );
1003
1004
}
1005
+
1006
+ // Rename "id" to "_id" for embedded documents
1007
+ $ fields = $ this ->aliasIdForQuery ($ fields );
1004
1008
}
1005
1009
1006
1010
$ options = $ this ->inheritConnectionOptions ($ options );
1007
1011
1008
1012
$ wheres = $ this ->compileWheres ();
1013
+
1009
1014
$ result = $ this ->collection ->updateMany ($ wheres , $ update , $ options );
1010
1015
if ($ result ->isAcknowledged ()) {
1011
1016
return $ result ->getModifiedCount () ? $ result ->getModifiedCount () : $ result ->getUpsertedCount ();
@@ -1188,7 +1193,7 @@ protected function compileWheres(): array
1188
1193
}
1189
1194
}
1190
1195
1191
- return $ compiled ;
1196
+ return $ this -> aliasIdForQuery ( $ compiled) ;
1192
1197
}
1193
1198
1194
1199
protected function compileWhereBasic (array $ where ): array
@@ -1561,13 +1566,52 @@ private function aliasIdForQuery(array $values): array
1561
1566
unset($ values ['id ' ]);
1562
1567
}
1563
1568
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
+
1564
1584
return $ values ;
1565
1585
}
1566
1586
1567
- private function aliasIdForResult (array $ values ): array
1587
+ private function aliasIdForResult (stdClass | array $ values ): stdClass | array
1568
1588
{
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
+ }
1571
1615
}
1572
1616
1573
1617
return $ values ;
0 commit comments