Skip to content

Commit 8bbcdbf

Browse files
committed
PHPORM-147 Make id an alias for _id
1 parent 73c18e9 commit 8bbcdbf

File tree

5 files changed

+195
-83
lines changed

5 files changed

+195
-83
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# Changelog
22
All notable changes to this project will be documented in this file.
33

4+
## [5.0.0] - next
5+
6+
* **BREAKING CHANGE** Use `id` as an alias for `_id` in commands and queries for compatibility with Eloquent packages by @GromNaN in [#3040](https://github.com/mongodb/laravel-mongodb/pull/3040)
7+
48
## [4.8.0] - next
59

610
* Add `Query\Builder::incrementEach()` and `decrementEach()` methods by @SmallRuralDog in [#2550](https://github.com/mongodb/laravel-mongodb/pull/2550)

src/Query/Builder.php

+73-36
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ public function toMql(): array
375375

376376
// Apply order and limit
377377
if ($this->orders) {
378-
$pipeline[] = ['$sort' => $this->orders];
378+
$pipeline[] = ['$sort' => $this->aliasIdForQuery($this->orders)];
379379
}
380380

381381
if ($this->offset) {
@@ -416,7 +416,7 @@ public function toMql(): array
416416

417417
// Normal query
418418
// Convert select columns to simple projections.
419-
$projection = array_fill_keys($columns, true);
419+
$projection = $this->aliasIdForQuery(array_fill_keys($columns, true));
420420

421421
// Add custom projections.
422422
if ($this->projections) {
@@ -431,7 +431,7 @@ public function toMql(): array
431431
}
432432

433433
if ($this->orders) {
434-
$options['sort'] = $this->orders;
434+
$options['sort'] = $this->aliasIdForQuery($this->orders);
435435
}
436436

437437
if ($this->offset) {
@@ -506,7 +506,7 @@ public function getFresh($columns = [], $returnLazy = false)
506506
if ($returnLazy) {
507507
return LazyCollection::make(function () use ($result) {
508508
foreach ($result as $item) {
509-
yield $item;
509+
yield $this->aliasIdForResult($item);
510510
}
511511
});
512512
}
@@ -515,6 +515,10 @@ public function getFresh($columns = [], $returnLazy = false)
515515
$result = $result->toArray();
516516
}
517517

518+
foreach ($result as &$document) {
519+
$document = $this->aliasIdForResult($document);
520+
}
521+
518522
return new Collection($result);
519523
}
520524

@@ -593,7 +597,7 @@ public function aggregate($function = null, $columns = ['*'])
593597
/** @inheritdoc */
594598
public function exists()
595599
{
596-
return $this->first(['_id']) !== null;
600+
return $this->first(['id']) !== null;
597601
}
598602

599603
/** @inheritdoc */
@@ -682,6 +686,18 @@ public function insert(array $values)
682686
$values = [$values];
683687
}
684688

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

687703
$result = $this->collection->insertMany($values, $options);
@@ -700,11 +716,10 @@ public function insertGetId(array $values, $sequence = null)
700716
return null;
701717
}
702718

703-
if ($sequence === null || $sequence === '_id') {
704-
return $result->getInsertedId();
705-
}
706-
707-
return $values[$sequence];
719+
return match ($sequence) {
720+
'_id', 'id', null => $result->getInsertedId(),
721+
default => $values[$sequence],
722+
};
708723
}
709724

710725
/** @inheritdoc */
@@ -720,7 +735,12 @@ public function update(array $values, array $options = [])
720735
unset($values[$key]);
721736
}
722737

723-
$options = $this->inheritConnectionOptions($options);
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+
}
724744

725745
return $this->performUpdate($values, $options);
726746
}
@@ -821,18 +841,6 @@ public function decrementEach(array $columns, array $extra = [], array $options
821841
return $this->incrementEach($decrement, $extra, $options);
822842
}
823843

824-
/** @inheritdoc */
825-
public function chunkById($count, callable $callback, $column = '_id', $alias = null)
826-
{
827-
return parent::chunkById($count, $callback, $column, $alias);
828-
}
829-
830-
/** @inheritdoc */
831-
public function forPageAfterId($perPage = 15, $lastId = 0, $column = '_id')
832-
{
833-
return parent::forPageAfterId($perPage, $lastId, $column);
834-
}
835-
836844
/** @inheritdoc */
837845
public function pluck($column, $key = null)
838846
{
@@ -1048,21 +1056,26 @@ public function runPaginationCountQuery($columns = ['*'])
10481056
/**
10491057
* Perform an update query.
10501058
*
1051-
* @param array $query
1052-
*
10531059
* @return int
10541060
*/
1055-
protected function performUpdate($query, array $options = [])
1061+
protected function performUpdate(array $update, array $options = [])
10561062
{
10571063
// Update multiple items by default.
10581064
if (! array_key_exists('multiple', $options)) {
10591065
$options['multiple'] = true;
10601066
}
10611067

1068+
// Since "id" is an alias for "_id", we prevent updating it
1069+
foreach ($update as $operator => $fields) {
1070+
if (array_key_exists('id', $fields)) {
1071+
throw new InvalidArgumentException('Cannot update "id" field.');
1072+
}
1073+
}
1074+
10621075
$options = $this->inheritConnectionOptions($options);
10631076

10641077
$wheres = $this->compileWheres();
1065-
$result = $this->collection->updateMany($wheres, $query, $options);
1078+
$result = $this->collection->updateMany($wheres, $update, $options);
10661079
if ($result->isAcknowledged()) {
10671080
return $result->getModifiedCount() ? $result->getModifiedCount() : $result->getUpsertedCount();
10681081
}
@@ -1155,16 +1168,21 @@ protected function compileWheres(): array
11551168
// Convert column name to string to use as array key
11561169
if (isset($where['column'])) {
11571170
$where['column'] = (string) $where['column'];
1158-
}
11591171

1160-
// Convert id's.
1161-
if (isset($where['column']) && ($where['column'] === '_id' || str_ends_with($where['column'], '._id'))) {
1162-
if (isset($where['values'])) {
1163-
// Multiple values.
1164-
$where['values'] = array_map($this->convertKey(...), $where['values']);
1165-
} elseif (isset($where['value'])) {
1166-
// Single value.
1167-
$where['value'] = $this->convertKey($where['value']);
1172+
// Compatibility with Eloquent queries that uses "id" instead of MongoDB's _id
1173+
if ($where['column'] === 'id') {
1174+
$where['column'] = '_id';
1175+
}
1176+
1177+
// Convert id's.
1178+
if ($where['column'] === '_id' || str_ends_with($where['column'], '._id')) {
1179+
if (isset($where['values'])) {
1180+
// Multiple values.
1181+
$where['values'] = array_map($this->convertKey(...), $where['values']);
1182+
} elseif (isset($where['value'])) {
1183+
// Single value.
1184+
$where['value'] = $this->convertKey($where['value']);
1185+
}
11681186
}
11691187
}
11701188

@@ -1604,4 +1622,23 @@ public function orWhereIntegerNotInRaw($column, $values, $boolean = 'and')
16041622
{
16051623
throw new BadMethodCallException('This method is not supported by MongoDB');
16061624
}
1625+
1626+
private function aliasIdForQuery(array $values): array
1627+
{
1628+
if (isset($values['id'])) {
1629+
$values['_id'] = $values['id'];
1630+
unset($values['id']);
1631+
}
1632+
1633+
return $values;
1634+
}
1635+
1636+
private function aliasIdForResult(array $values): array
1637+
{
1638+
if (isset($values['_id'])) {
1639+
$values['id'] = $values['_id'];
1640+
}
1641+
1642+
return $values;
1643+
}
16071644
}

0 commit comments

Comments
 (0)