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 bd9ef30

Browse files
authored
PHPORM-230 Convert DateTimeInterface to UTCDateTime in queries (#3105)
* PHPORM-230 Convert DateTimeInterface to UTCDateTime in queries * Alias id to _id in subdocuments
1 parent d2c6de9 commit bd9ef30

File tree

4 files changed

+37
-51
lines changed

4 files changed

+37
-51
lines changed

‎src/Query/Builder.php‎

Lines changed: 21 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
use function array_map;
3333
use function array_merge;
3434
use function array_values;
35-
use function array_walk_recursive;
3635
use function assert;
3736
use function blank;
3837
use function call_user_func;
@@ -689,17 +688,7 @@ public function insert(array $values)
689688
$values = [$values];
690689
}
691690

692-
// Compatibility with Eloquent queries that uses "id" instead of MongoDB's _id
693-
foreach ($values as &$document) {
694-
if (isset($document['id'])) {
695-
if (isset($document['_id']) && $document['_id'] !== $document['id']) {
696-
throw new InvalidArgumentException('Cannot insert document with different "id" and "_id" values');
697-
}
698-
699-
$document['_id'] = $document['id'];
700-
unset($document['id']);
701-
}
702-
}
691+
$values = $this->aliasIdForQuery($values);
703692

704693
$options = $this->inheritConnectionOptions();
705694

@@ -876,6 +865,7 @@ public function delete($id = null)
876865
}
877866

878867
$wheres = $this->compileWheres();
868+
$wheres = $this->aliasIdForQuery($wheres);
879869
$options = $this->inheritConnectionOptions();
880870

881871
if (is_int($this->limit)) {
@@ -1070,16 +1060,12 @@ protected function performUpdate(array $update, array $options = [])
10701060
$options['multiple'] = true;
10711061
}
10721062

1073-
// Since "id" is an alias for "_id", we prevent updating it
1074-
foreach ($update as $operator => $fields) {
1075-
if (array_key_exists('id', $fields)) {
1076-
throw new InvalidArgumentException('Cannot update "id" field.');
1077-
}
1078-
}
1063+
$update = $this->aliasIdForQuery($update);
10791064

10801065
$options = $this->inheritConnectionOptions($options);
10811066

10821067
$wheres = $this->compileWheres();
1068+
$wheres = $this->aliasIdForQuery($wheres);
10831069
$result = $this->collection->updateMany($wheres, $update, $options);
10841070
if ($result->isAcknowledged()) {
10851071
return $result->getModifiedCount() ? $result->getModifiedCount() : $result->getUpsertedCount();
@@ -1191,32 +1177,12 @@ protected function compileWheres(): array
11911177
}
11921178
}
11931179

1194-
// Convert DateTime values to UTCDateTime.
1195-
if (isset($where['value'])) {
1196-
if (is_array($where['value'])) {
1197-
array_walk_recursive($where['value'], function (&$item, $key) {
1198-
if ($item instanceof DateTimeInterface) {
1199-
$item = new UTCDateTime($item);
1200-
}
1201-
});
1202-
} else {
1203-
if ($where['value'] instanceof DateTimeInterface) {
1204-
$where['value'] = new UTCDateTime($where['value']);
1205-
}
1206-
}
1207-
} elseif (isset($where['values'])) {
1208-
if (is_array($where['values'])) {
1209-
array_walk_recursive($where['values'], function (&$item, $key) {
1210-
if ($item instanceof DateTimeInterface) {
1211-
$item = new UTCDateTime($item);
1212-
}
1213-
});
1214-
} elseif ($where['values'] instanceof CarbonPeriod) {
1215-
$where['values'] = [
1216-
new UTCDateTime($where['values']->getStartDate()),
1217-
new UTCDateTime($where['values']->getEndDate()),
1218-
];
1219-
}
1180+
// Convert CarbonPeriod to DateTime interval.
1181+
if (isset($where['values']) && $where['values'] instanceof CarbonPeriod) {
1182+
$where['values'] = [
1183+
$where['values']->getStartDate(),
1184+
$where['values']->getEndDate(),
1185+
];
12201186
}
12211187

12221188
// In a sequence of "where" clauses, the logical operator of the
@@ -1631,12 +1597,21 @@ public function orWhereIntegerNotInRaw($column, $values, $boolean = 'and')
16311597
private function aliasIdForQuery(array $values): array
16321598
{
16331599
if (array_key_exists('id', $values)) {
1600+
if (array_key_exists('_id', $values)) {
1601+
throw new InvalidArgumentException('Cannot have both "id" and "_id" fields.');
1602+
}
1603+
16341604
$values['_id'] = $values['id'];
16351605
unset($values['id']);
16361606
}
16371607

16381608
foreach ($values as $key => $value) {
16391609
if (is_string($key) && str_ends_with($key, '.id')) {
1610+
$newkey = substr($key, 0, -3) . '._id';
1611+
if (array_key_exists($newkey, $values)) {
1612+
throw new InvalidArgumentException(sprintf('Cannot have both "%s" and "%s" fields.', $key, $newkey));
1613+
}
1614+
16401615
$values[substr($key, 0, -3) . '._id'] = $value;
16411616
unset($values[$key]);
16421617
}
@@ -1645,6 +1620,8 @@ private function aliasIdForQuery(array $values): array
16451620
foreach ($values as &$value) {
16461621
if (is_array($value)) {
16471622
$value = $this->aliasIdForQuery($value);
1623+
} elseif ($value instanceof DateTimeInterface) {
1624+
$value = new UTCDateTime($value);
16481625
}
16491626
}
16501627

‎tests/Query/AggregationBuilderTest.php‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
use InvalidArgumentException;
1212
use MongoDB\BSON\Document;
1313
use MongoDB\BSON\ObjectId;
14-
use MongoDB\BSON\UTCDateTime;
1514
use MongoDB\Builder\BuilderEncoder;
1615
use MongoDB\Builder\Expression;
1716
use MongoDB\Builder\Pipeline;
@@ -33,8 +32,8 @@ public function tearDown(): void
3332
public function testCreateAggregationBuilder(): void
3433
{
3534
User::insert([
36-
['name' => 'John Doe', 'birthday' => new UTCDateTime(newDateTimeImmutable('1989年01月01日'))],
37-
['name' => 'Jane Doe', 'birthday' => new UTCDateTime(newDateTimeImmutable('1990年01月01日'))],
35+
['name' => 'John Doe', 'birthday' => new DateTimeImmutable('1989年01月01日')],
36+
['name' => 'Jane Doe', 'birthday' => new DateTimeImmutable('1990年01月01日')],
3837
]);
3938

4039
// Create the aggregation pipeline from the query builder

‎tests/Query/BuilderTest.php‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,12 @@ function (Builder $builder) {
566566
fn (Builder $builder) => $builder->whereBetween('id', [[1], [2, 3]]),
567567
];
568568

569+
$date = new DateTimeImmutable('2018年09月30日 15:00:00 +02:00');
570+
yield 'where $lt DateTimeInterface' => [
571+
['find' => [['created_at' => ['$lt' => new UTCDateTime($date)]], []]],
572+
fn (Builder $builder) => $builder->where('created_at', '<', $date),
573+
];
574+
569575
$period = now()->toPeriod(now()->addMonth());
570576
yield 'whereBetween CarbonPeriod' => [
571577
[

‎tests/QueryBuilderTest.php‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,16 +1053,20 @@ public function testIncrementEach()
10531053
#[TestWith(['id', 'id'])]
10541054
#[TestWith(['id', '_id'])]
10551055
#[TestWith(['_id', 'id'])]
1056+
#[TestWith(['_id', '_id'])]
10561057
public function testIdAlias($insertId, $queryId): void
10571058
{
1058-
DB::collection('items')->insert([$insertId => 'abc', 'name' => 'Karting']);
1059-
$item = DB::collection('items')->where($queryId, '=', 'abc')->first();
1059+
DB::table('items')->insert([$insertId => 'abc', 'name' => 'Karting']);
1060+
$item = DB::table('items')->where($queryId, '=', 'abc')->first();
10601061
$this->assertNotNull($item);
10611062
$this->assertSame('abc', $item['id']);
10621063
$this->assertSame('Karting', $item['name']);
10631064

1064-
DB::collection('items')->where($insertId, '=', 'abc')->update(['name' => 'Bike']);
1065-
$item = DB::collection('items')->where($queryId, '=', 'abc')->first();
1065+
DB::table('items')->where($insertId, '=', 'abc')->update(['name' => 'Bike']);
1066+
$item = DB::table('items')->where($queryId, '=', 'abc')->first();
10661067
$this->assertSame('Bike', $item['name']);
1068+
1069+
$result = DB::table('items')->where($queryId, '=', 'abc')->delete();
1070+
$this->assertSame(1, $result);
10671071
}
10681072
}

0 commit comments

Comments
(0)

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