Skip to content

Commit bb9f4df

Browse files
JayBizzletaylorotwell
authored andcommitted
[5.5] Use table aliases when calling self-referencing HasManyThrough relation (laravel#21883)
* Use table aliases when calling self-referencing HasManyThrough relation * alias the sub query table * fix style
1 parent d455b40 commit bb9f4df

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

src/Illuminate/Database/Eloquent/Relations/HasManyThrough.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
*
@@ -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
*

tests/Integration/Database/EloquentHasManyThroughTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public function basic_create_and_retrieve()
5656
$notMember = User::create(['name' => str_random()]);
5757

5858
$this->assertEquals([$mate1->id, $mate2->id], $user->teamMates->pluck('id')->toArray());
59+
$this->assertEquals([$user->id], User::has('teamMates')->pluck('id')->toArray());
5960
}
6061
}
6162

0 commit comments

Comments
 (0)