From c04958bc17bd98605df959e8ea98ad2db09a0c0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20D=C3=ADaz?= Date: Thu, 21 Sep 2017 15:43:29 +0200 Subject: [PATCH] Allow setting custom morphTo ownerKey. (#21310) --- .../Eloquent/Concerns/HasRelationships.php | 17 ++++++++++------- .../Database/Eloquent/Relations/MorphTo.php | 10 +++++++--- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php b/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php index d5599da4378c..a6d6f7ede8db 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php +++ b/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php @@ -128,9 +128,10 @@ public function belongsTo($related, $foreignKey = null, $ownerKey = null, $relat * @param string $name * @param string $type * @param string $id + * @param string $ownerKey * @return \Illuminate\Database\Eloquent\Relations\MorphTo */ - public function morphTo($name = null, $type = null, $id = null) + public function morphTo($name = null, $type = null, $id = null, $ownerKey = null) { // If no name is provided, we will use the backtrace to get the function name // since that is most likely the name of the polymorphic interface. We can @@ -145,8 +146,8 @@ public function morphTo($name = null, $type = null, $id = null) // the relationship. In this case we'll just pass in a dummy query where we // need to remove any eager loads that may already be defined on a model. return empty($class = $this->{$type}) - ? $this->morphEagerTo($name, $type, $id) - : $this->morphInstanceTo($class, $name, $type, $id); + ? $this->morphEagerTo($name, $type, $id, $ownerKey) + : $this->morphInstanceTo($class, $name, $type, $id, $ownerKey); } /** @@ -155,12 +156,13 @@ public function morphTo($name = null, $type = null, $id = null) * @param string $name * @param string $type * @param string $id + * @param string $ownerKey * @return \Illuminate\Database\Eloquent\Relations\MorphTo */ - protected function morphEagerTo($name, $type, $id) + protected function morphEagerTo($name, $type, $id, $ownerKey) { return new MorphTo( - $this->newQuery()->setEagerLoads([]), $this, $id, null, $type, $name + $this->newQuery()->setEagerLoads([]), $this, $id, $ownerKey, $type, $name ); } @@ -171,16 +173,17 @@ protected function morphEagerTo($name, $type, $id) * @param string $name * @param string $type * @param string $id + * @param string $ownerKey * @return \Illuminate\Database\Eloquent\Relations\MorphTo */ - protected function morphInstanceTo($target, $name, $type, $id) + protected function morphInstanceTo($target, $name, $type, $id, $ownerKey) { $instance = $this->newRelatedInstance( static::getActualClassNameForMorph($target) ); return new MorphTo( - $instance->newQuery(), $this, $id, $instance->getKeyName(), $type, $name + $instance->newQuery(), $this, $id, $ownerKey ?? $instance->getKeyName(), $type, $name ); } diff --git a/src/Illuminate/Database/Eloquent/Relations/MorphTo.php b/src/Illuminate/Database/Eloquent/Relations/MorphTo.php index 2739786d5e7e..073b887e8487 100644 --- a/src/Illuminate/Database/Eloquent/Relations/MorphTo.php +++ b/src/Illuminate/Database/Eloquent/Relations/MorphTo.php @@ -120,12 +120,14 @@ protected function getResultsByType($type) { $instance = $this->createModelByType($type); + $ownerKey = $this->ownerKey ?? $instance->getKeyName(); + $query = $this->replayMacros($instance->newQuery()) ->mergeConstraintsFrom($this->getQuery()) ->with($this->getQuery()->getEagerLoads()); return $query->whereIn( - $instance->getTable().'.'.$instance->getKeyName(), $this->gatherKeysByType($type) + $instance->getTable().'.'.$ownerKey, $this->gatherKeysByType($type) )->get(); } @@ -178,8 +180,10 @@ public function match(array $models, Collection $results, $relation) protected function matchToMorphParents($type, Collection $results) { foreach ($results as $result) { - if (isset($this->dictionary[$type][$result->getKey()])) { - foreach ($this->dictionary[$type][$result->getKey()] as $model) { + $ownerKey = ! is_null($this->ownerKey) ? $result->{$this->ownerKey} : $result->getKey(); + + if (isset($this->dictionary[$type][$ownerKey])) { + foreach ($this->dictionary[$type][$ownerKey] as $model) { $model->setRelation($this->relation, $result); } }