Skip to content

Commit 206f0f9

Browse files
divineAAllport
andcommitted
Add Attributes to the Pivot Embed
Co-Authored-By: Adam Allport <[email protected]>
1 parent 4d81b40 commit 206f0f9

File tree

7 files changed

+260
-28
lines changed

7 files changed

+260
-28
lines changed

src/Jenssegers/Mongodb/Relations/BelongsTo.php

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Jenssegers\Mongodb\Relations;
44

55
use Illuminate\Database\Eloquent\Builder;
6+
use Illuminate\Database\Eloquent\Collection;
67
use Illuminate\Database\Eloquent\Model as EloquentModel;
78

89
class BelongsTo extends \Illuminate\Database\Eloquent\Relations\BelongsTo
@@ -25,7 +26,9 @@ public function addConstraints()
2526
// For belongs to relationships, which are essentially the inverse of has one
2627
// or has many relationships, we need to actually query on the primary key
2728
// of the related models matching on the foreign key that's on a parent.
28-
$this->query->where($this->getOwnerKey(), '=', $this->parent->{$this->foreignKey});
29+
$this->query
30+
->where($this->getOwnerKey(), '=', $this->parent->{$this->foreignKey})
31+
->orWhere($this->getOwnerKey().'._id', '=', $this->parent->{$this->foreignKey});
2932
}
3033
}
3134

@@ -69,4 +72,29 @@ protected function whereInMethod(EloquentModel $model, $key)
6972
{
7073
return 'whereIn';
7174
}
75+
76+
/**
77+
* @inheritDoc
78+
*/
79+
public function match(array $models, Collection $results, $relation)
80+
{
81+
$foreign = $this->foreignKey;
82+
$owner = $this->ownerKey;
83+
// First we will get to build a dictionary of the child models by their primary
84+
// key of the relationship, then we can easily match the children back onto
85+
// the parents using that dictionary and the primary key of the children.
86+
$dictionary = [];
87+
foreach ($results as $result) {
88+
$dictionary[$result->getAttribute($owner)] = $result;
89+
}
90+
// Once we have the dictionary constructed, we can loop through all the parents
91+
// and match back onto their children using these keys of the dictionary and
92+
// the primary key of the children to map them onto the correct instances.
93+
foreach ($models as $model) {
94+
if (isset($dictionary[(string) $model->{$foreign}])) {
95+
$model->setRelation($relation, $dictionary[(string) $model->{$foreign}]);
96+
}
97+
}
98+
return $models;
99+
}
72100
}

src/Jenssegers/Mongodb/Relations/BelongsToMany.php

Lines changed: 75 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,13 @@ public function getRelationExistenceQuery(Builder $query, Builder $parentQuery,
3333
*/
3434
protected function hydratePivotRelation(array $models)
3535
{
36-
// Do nothing.
36+
foreach ($models as $model) {
37+
$keyToUse = $this->getTable() == $model->getTable() ? $this->getForeignKey() : $this->getRelatedKey();
38+
$pcontent = $model->getAttributes()[$keyToUse];
39+
$model->setRelation($this->accessor, $this->newExistingPivot(
40+
is_string($pcontent[0]) ? ['_id' => $pcontent] : $pcontent[0]
41+
));
42+
}
3743
}
3844

3945
/**
@@ -71,8 +77,10 @@ public function addConstraints()
7177
protected function setWhere()
7278
{
7379
$foreign = $this->getForeignKey();
74-
75-
$this->query->where($foreign, '=', $this->parent->getKey());
80+
$key = $this->parent->getKey();
81+
$this->query
82+
->where($foreign, '=', $key)
83+
->orWhereRaw([$foreign.'._id' => $key]);
7684

7785
return $this;
7886
}
@@ -129,6 +137,12 @@ public function sync($ids, $detaching = true)
129137
// See issue #256.
130138
if ($current instanceof Collection) {
131139
$current = $ids->modelKeys();
140+
} elseif (is_array($current)) {
141+
foreach ($current as $key => $value) {
142+
if (is_array($value) && $value['_id']) {
143+
$current[$key] = $value['_id'];
144+
}
145+
}
132146
}
133147

134148
$records = $this->formatSyncList($ids);
@@ -171,7 +185,30 @@ public function sync($ids, $detaching = true)
171185
*/
172186
public function updateExistingPivot($id, array $attributes, $touch = true)
173187
{
174-
// Do nothing, we have no pivot table.
188+
if ($id instanceof Model) {
189+
$model = $id;
190+
$id = $model->getKey();
191+
} else {
192+
if ($id instanceof Collection) {
193+
$id = $id->modelKeys();
194+
}
195+
196+
$related = $this->newRelatedQuery()->whereIn($this->related->getKeyName(), (array) $id);
197+
$filter = [$this->parentKey => $this->parent->getKey()];
198+
$pivot_x = [array_merge($attributes, $filter)];
199+
200+
//TODO: Put this in a transaction
201+
$related->pull($this->getForeignKey(), $this->parent->getKey());
202+
$related->pull($this->getForeignKey(), $filter);
203+
$related->push($this->getForeignKey(), $pivot_x, true);
204+
}
205+
$filter = [$this->parentKey => $id];
206+
$pivot_x = [array_merge($attributes, $filter)];
207+
208+
//TODO: Put this in a transaction
209+
$this->parent->pull($this->getRelatedKey(), $id);
210+
$this->parent->pull($this->getRelatedKey(), $filter);
211+
$this->parent->push($this->getRelatedKey(), $pivot_x, true);
175212
}
176213

177214
/**
@@ -185,22 +222,30 @@ public function attach($id, array $attributes = [], $touch = true)
185222
$id = $model->getKey();
186223

187224
// Attach the new parent id to the related model.
188-
$model->push($this->foreignPivotKey, $this->parent->getKey(), true);
225+
$model->push($this->foreignPivotKey, [array_merge($attributes, ['_id' => $this->parent->getKey()])], true);
189226
} else {
190227
if ($id instanceof Collection) {
191228
$id = $id->modelKeys();
192229
}
193230

194231
$query = $this->newRelatedQuery();
195232

196-
$query->whereIn($this->related->getKeyName(), (array) $id);
233+
$query
234+
->whereIn($this->related->getKeyName(), (array) $id)
235+
->orWhereIn($this->related->getKeyName().'._id', (array) $id);
197236

198237
// Attach the new parent id to the related model.
199-
$query->push($this->foreignPivotKey, $this->parent->getKey(), true);
238+
$query->push($this->foreignPivotKey, [array_merge($attributes, ['_id' => $this->parent->getKey()])], true);
239+
}
240+
241+
//Pivot Collection
242+
$pivot_x = [];
243+
foreach ((array) $id as $item) {
244+
$pivot_x[] = array_merge($attributes, ['_id' => $item]);
200245
}
201246

202247
// Attach the new ids to the parent model.
203-
$this->parent->push($this->getRelatedKey(), (array) $id, true);
248+
$this->parent->push($this->getRelatedKey(), $pivot_x, true);
204249

205250
if ($touch) {
206251
$this->touchIfTouching();
@@ -224,7 +269,9 @@ public function detach($ids = [], $touch = true)
224269
$ids = (array) $ids;
225270

226271
// Detach all ids from the parent model.
272+
// Legacy Support
227273
$this->parent->pull($this->getRelatedKey(), $ids);
274+
$this->parent->pull($this->getRelatedKey(), ['_id' => ['$in' => $ids]]);
228275

229276
// Prepare the query to select all related objects.
230277
if (count($ids) > 0) {
@@ -233,6 +280,7 @@ public function detach($ids = [], $touch = true)
233280

234281
// Remove the relation to the parent.
235282
$query->pull($this->foreignPivotKey, $this->parent->getKey());
283+
$query->pull($this->foreignPivotKey, [$this->parentKey => $this->parent->getKey()]);
236284

237285
if ($touch) {
238286
$this->touchIfTouching();
@@ -253,10 +301,14 @@ protected function buildDictionary(Collection $results)
253301
// parents without having a possibly slow inner loops for every models.
254302
$dictionary = [];
255303

256-
foreach ($results as $result) {
257-
foreach ($result->$foreign as $item) {
258-
$dictionary[$item][] = $result;
259-
}
304+
foreach ($results as $result) {
305+
foreach ($result->$foreign as $item) {
306+
if (is_array($item)) {
307+
$dictionary[$item['_id']][] = $result;
308+
} else {
309+
$dictionary[$item][] = $result;
310+
}
311+
}
260312
}
261313

262314
return $dictionary;
@@ -342,4 +394,15 @@ protected function whereInMethod(EloquentModel $model, $key)
342394
{
343395
return 'whereIn';
344396
}
397+
398+
/**
399+
* @inheritDoc
400+
*/
401+
public function addEagerConstraints(array $models)
402+
{
403+
$keys = $this->getKeys($models, $this->parentKey);
404+
$this->query
405+
->whereIn($this->getQualifiedForeignPivotKeyName(), $keys)
406+
->orWhereRaw([$this->getQualifiedForeignPivotKeyName().'._id' => ['$in' => $keys]]);
407+
}
345408
}

src/Jenssegers/Mongodb/Relations/HasMany.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Jenssegers\Mongodb\Relations;
44

55
use Illuminate\Database\Eloquent\Builder;
6+
use Illuminate\Database\Eloquent\Collection;
67
use Illuminate\Database\Eloquent\Model as EloquentModel;
78
use Illuminate\Database\Eloquent\Relations\HasMany as EloquentHasMany;
89

@@ -71,7 +72,9 @@ public function getRelationQuery(Builder $query, Builder $parent, $columns = ['*
7172

7273
$key = $this->wrap($this->getQualifiedParentKeyName());
7374

74-
return $query->where($this->getHasCompareKey(), 'exists', true);
75+
return $query
76+
->where($this->getHasCompareKey(), 'exists', true)
77+
->orWhere($this->getHasCompareKey().'._id', 'exists', true);
7578
}
7679

7780
/**
@@ -84,4 +87,13 @@ protected function whereInMethod(EloquentModel $model, $key)
8487
{
8588
return 'whereIn';
8689
}
90+
91+
protected function buildDictionary(Collection $results)
92+
{
93+
$foreign = $this->getForeignKeyName();
94+
95+
return $results->mapToDictionary(function ($result) use ($foreign) {
96+
return [(string) $result->{$foreign} => $result];
97+
})->all();
98+
}
8799
}

src/Jenssegers/Mongodb/Relations/HasOne.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Jenssegers\Mongodb\Relations;
44

55
use Illuminate\Database\Eloquent\Builder;
6+
use Illuminate\Database\Eloquent\Collection;
67
use Illuminate\Database\Eloquent\Model as EloquentModel;
78
use Illuminate\Database\Eloquent\Relations\HasOne as EloquentHasOne;
89

@@ -84,4 +85,16 @@ protected function whereInMethod(EloquentModel $model, $key)
8485
{
8586
return 'whereIn';
8687
}
88+
89+
/**
90+
* @inheritdoc
91+
*/
92+
protected function buildDictionary(Collection $results)
93+
{
94+
$foreign = $this->getForeignKeyName();
95+
96+
return $results->mapToDictionary(function ($result) use ($foreign) {
97+
return [(string) $result->{$foreign} => $result];
98+
})->all();
99+
}
87100
}

src/Jenssegers/Mongodb/Relations/MorphMany.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Jenssegers\Mongodb\Relations;
44

5+
use Illuminate\Database\Eloquent\Collection;
56
use Illuminate\Database\Eloquent\Model as EloquentModel;
67
use Illuminate\Database\Eloquent\Relations\MorphMany as EloquentMorphMany;
78

@@ -19,4 +20,17 @@ protected function whereInMethod(EloquentModel $model, $key)
1920
{
2021
return 'whereIn';
2122
}
23+
24+
/**
25+
* @inheritdoc
26+
*/
27+
protected function buildDictionary(Collection $results)
28+
{
29+
$foreign = $this->getForeignKeyName();
30+
31+
return $results->mapToDictionary(function ($result) use ($foreign) {
32+
return [(string) $result->{$foreign} => $result];
33+
})->all();
34+
35+
}
2236
}

src/Jenssegers/Mongodb/Relations/MorphTo.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Jenssegers\Mongodb\Relations;
44

5+
use Illuminate\Database\Eloquent\Collection;
56
use Illuminate\Database\Eloquent\Model as EloquentModel;
67
use Illuminate\Database\Eloquent\Relations\MorphTo as EloquentMorphTo;
78

@@ -53,4 +54,16 @@ protected function whereInMethod(EloquentModel $model, $key)
5354
{
5455
return 'whereIn';
5556
}
57+
58+
/**
59+
* @inheritDoc
60+
*/
61+
protected function buildDictionary(Collection $models)
62+
{
63+
foreach ($models as $model) {
64+
if ($model->{$this->morphType}) {
65+
$this->dictionary[$model->{$this->morphType}][(string) $model->{$this->foreignKey}][] = $model;
66+
}
67+
}
68+
}
5669
}

0 commit comments

Comments
 (0)