@@ -52,6 +52,13 @@ class HasManyThrough extends Relation
5252 */
5353 protected $ secondLocalKey ;
5454
55+ /**
56+ * The count of self joins.
57+ *
58+ * @var int
59+ */
60+ protected static $ selfJoinCount = 0 ;
61+
5562 /**
5663 * Create a new has many through relationship instance.
5764 *
@@ -178,7 +185,7 @@ public function match(array $models, Collection $results, $relation)
178185 // link them up with their children using the keyed dictionary to make the
179186 // matching very convenient and easy work. Then we'll just return them.
180187 foreach ($ models as $ model ) {
181- if (isset ($ dictionary [$ key = $ model ->getKey ( )])) {
188+ if (isset ($ dictionary [$ key = $ model ->getAttribute ( $ this -> localKey )])) {
182189 $ model ->setRelation (
183190 $ relation , $ this ->related ->newCollection ($ dictionary [$ key ])
184191 );
@@ -425,13 +432,52 @@ protected function shouldSelect(array $columns = ['*'])
425432 */
426433 public function getRelationExistenceQuery (Builder $ query , Builder $ parentQuery , $ columns = ['* ' ])
427434 {
435+ if ($ parentQuery ->getQuery ()->from == $ query ->getQuery ()->from ) {
436+ return $ this ->getRelationExistenceQueryForSelfRelation ($ query , $ parentQuery , $ columns );
437+ }
438+
428439 $ this ->performJoin ($ query );
429440
430441 return $ query ->select ($ columns )->whereColumn (
431442 $ this ->getExistenceCompareKey (), '= ' , $ this ->getQualifiedFirstKeyName ()
432443 );
433444 }
434445
446+ /**
447+ * Add the constraints for a relationship query on the same table.
448+ *
449+ * @param \Illuminate\Database\Eloquent\Builder $query
450+ * @param \Illuminate\Database\Eloquent\Builder $parentQuery
451+ * @param array|mixed $columns
452+ * @return \Illuminate\Database\Eloquent\Builder
453+ */
454+ public function getRelationExistenceQueryForSelfRelation (Builder $ query , Builder $ parentQuery , $ columns = ['* ' ])
455+ {
456+ $ query ->from ($ query ->getModel ()->getTable ().' as ' .$ hash = $ this ->getRelationCountHash ());
457+
458+ $ query ->join ($ this ->throughParent ->getTable (), $ this ->getQualifiedParentKeyName (), '= ' , $ hash .'. ' .$ this ->secondLocalKey );
459+
460+ if ($ this ->throughParentSoftDeletes ()) {
461+ $ query ->whereNull ($ this ->throughParent ->getQualifiedDeletedAtColumn ());
462+ }
463+
464+ $ query ->getModel ()->setTable ($ hash );
465+
466+ return $ query ->select ($ columns )->whereColumn (
467+ $ parentQuery ->getQuery ()->from .'. ' .$ query ->getModel ()->getKeyName (), '= ' , $ this ->getQualifiedFirstKeyName ()
468+ );
469+ }
470+
471+ /**
472+ * Get a relationship join table hash.
473+ *
474+ * @return string
475+ */
476+ public function getRelationCountHash ()
477+ {
478+ return 'laravel_reserved_ ' .static ::$ selfJoinCount ++;
479+ }
480+
435481 /**
436482 * Get the key for comparing against the parent key in "has" query.
437483 *
0 commit comments