Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit fcff84e

Browse files
committed
PHPORM-239 Convert raw results to eloquent models, only when _id or id is returned
1 parent 07a44cc commit fcff84e

File tree

3 files changed

+46
-23
lines changed

3 files changed

+46
-23
lines changed

‎src/Eloquent/Builder.php‎

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace MongoDB\Laravel\Eloquent;
66

77
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
8+
use MongoDB\BSON\Document;
89
use MongoDB\Driver\CursorInterface;
910
use MongoDB\Driver\Exception\WriteException;
1011
use MongoDB\Laravel\Connection;
@@ -16,7 +17,9 @@
1617
use function array_merge;
1718
use function collect;
1819
use function is_array;
20+
use function is_object;
1921
use function iterator_to_array;
22+
use function property_exists;
2023

2124
/** @method \MongoDB\Laravel\Query\Builder toBase() */
2225
class Builder extends EloquentBuilder
@@ -178,21 +181,26 @@ public function raw($value = null)
178181

179182
// Convert MongoCursor results to a collection of models.
180183
if ($results instanceof CursorInterface) {
181-
$results = iterator_to_array($results, false);
184+
$results->setTypeMap(['root' => 'array', 'document' => 'array', 'array' => 'array']);
185+
$results = $this->query->aliasIdForResult(iterator_to_array($results));
182186

183187
return $this->model->hydrate($results);
184188
}
185189

186-
// Convert MongoDB BSONDocument to a single object.
187-
if ($results instanceof BSONDocument) {
188-
$results = $results->getArrayCopy();
189-
190-
return $this->model->newFromBuilder((array) $results);
190+
// Convert MongoDB Document to a single object.
191+
if (is_object($results) && (property_exists($results, '_id') || property_exists($results, 'id'))) {
192+
$results = (array) match (true) {
193+
$results instanceof BSONDocument => $results->getArrayCopy(),
194+
$results instanceof Document => $results->toPHP(['root' => 'array', 'document' => 'array', 'array' => 'array']),
195+
default => $results,
196+
};
191197
}
192198

193199
// The result is a single object.
194-
if (is_array($results) && array_key_exists('_id', $results)) {
195-
return $this->model->newFromBuilder((array) $results);
200+
if (is_array($results) && (array_key_exists('_id', $results) || array_key_exists('id', $results))) {
201+
$results = $this->query->aliasIdForResult($results);
202+
203+
return $this->model->newFromBuilder($results);
196204
}
197205

198206
return $results;

‎src/Query/Builder.php‎

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@
2020
use InvalidArgumentException;
2121
use LogicException;
2222
use MongoDB\BSON\Binary;
23+
use MongoDB\BSON\Document;
2324
use MongoDB\BSON\ObjectID;
2425
use MongoDB\BSON\Regex;
2526
use MongoDB\BSON\UTCDateTime;
2627
use MongoDB\Builder\Stage\FluentFactoryTrait;
2728
use MongoDB\Driver\Cursor;
28-
use MongoDB\Driver\CursorInterface;
2929
use Override;
3030
use RuntimeException;
3131
use stdClass;
@@ -935,17 +935,7 @@ public function raw($value = null)
935935
{
936936
// Execute the closure on the mongodb collection
937937
if ($value instanceof Closure) {
938-
$results = call_user_func($value, $this->collection);
939-
940-
if ($results instanceof CursorInterface) {
941-
$results = $results->toArray();
942-
}
943-
944-
if (is_array($results) || is_object($results)) {
945-
$results = $this->aliasIdForResult($results);
946-
}
947-
948-
return $results;
938+
return call_user_func($value, $this->collection);
949939
}
950940

951941
// Create an expression for the given value
@@ -1659,13 +1649,15 @@ private function aliasIdForQuery(array $values): array
16591649
}
16601650

16611651
/**
1652+
* @internal
1653+
*
16621654
* @psalm-param T $values
16631655
*
16641656
* @psalm-return T
16651657
*
16661658
* @template T of array|object
16671659
*/
1668-
private function aliasIdForResult(array|object $values): array|object
1660+
public function aliasIdForResult(array|object $values): array|object
16691661
{
16701662
if (is_array($values)) {
16711663
if (array_key_exists('_id', $values) && ! array_key_exists('id', $values)) {

‎tests/ModelTest.php‎

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -908,10 +908,17 @@ public function testRaw(): void
908908
$this->assertInstanceOf(User::class, $users[0]);
909909

910910
$user = User::raw(function (Collection $collection) {
911-
return $collection->findOne(['age' => 35]);
911+
return $collection->findOne(
912+
['age' => 35],
913+
['projection' => ['_id' => 1, 'name' => 1, 'age' => 1, 'now' => '$$NOW']],
914+
);
912915
});
913916

914-
$this->assertTrue(Model::isDocumentModel($user));
917+
$this->assertInstanceOf(User::class, $user);
918+
$this->assertArrayNotHasKey('_id', $user->getAttributes());
919+
$this->assertArrayHasKey('id', $user->getAttributes());
920+
$this->assertNotEmpty($user->id);
921+
$this->assertInstanceOf(Carbon::class, $user->now);
915922

916923
$count = User::raw(function (Collection $collection) {
917924
return $collection->count();
@@ -922,6 +929,22 @@ public function testRaw(): void
922929
return $collection->insertOne(['name' => 'Yvonne Yoe', 'age' => 35]);
923930
});
924931
$this->assertNotNull($result);
932+
933+
$result = User::raw(function (Collection $collection) {
934+
return $collection->aggregate([
935+
['$set' => ['now' => '$$NOW']],
936+
['$limit' => 2],
937+
]);
938+
});
939+
940+
$this->assertInstanceOf(EloquentCollection::class, $result);
941+
$this->assertCount(2, $result);
942+
$user = $result->first();
943+
$this->assertInstanceOf(User::class, $user);
944+
$this->assertArrayNotHasKey('_id', $user->getAttributes());
945+
$this->assertArrayHasKey('id', $user->getAttributes());
946+
$this->assertNotEmpty($user->id);
947+
$this->assertInstanceOf(Carbon::class, $user->now);
925948
}
926949

927950
public function testDotNotation(): void

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /