Skip to content

Commit

Permalink
Handle through-self-relation existence queries
Browse files Browse the repository at this point in the history
  • Loading branch information
staudenmeir committed Aug 21, 2021
1 parent c239bd6 commit 658ad96
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 1 deletion.
27 changes: 26 additions & 1 deletion src/HasManyDeep.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Staudenmeir\EloquentHasManyDeep;

use Exception;
use Illuminate\Contracts\Pagination\Paginator;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
Expand Down Expand Up @@ -288,6 +289,28 @@ public function chunk($count, callable $callback)
*/
public function getRelationExistenceQuery(Builder $query, Builder $parentQuery, $columns = ['*'])
{
foreach ($this->throughParents as $throughParent) {
if ($throughParent->getTable() === $parentQuery->getQuery()->from) {
if (!in_array(HasTableAlias::class, class_uses_recursive($throughParent))) {
$traitClass = HasTableAlias::class;
$throughParentClass = get_class($throughParent);

throw new Exception(
<<<EOT
This query requires an additional trait. Please add the $traitClass trait to $throughParentClass.
See https://github.com/staudenmeir/eloquent-has-many-deep/issues/137 for details.
EOT
);
}

$table = $throughParent->getTable() . ' as ' . $this->getRelationCountHash();

$throughParent->setTable($table);

break;
}
}

$query = parent::getRelationExistenceQuery($query, $parentQuery, $columns);

if (is_array($this->foreignKeys[0])) {
Expand All @@ -309,7 +332,9 @@ public function getRelationExistenceQuery(Builder $query, Builder $parentQuery,
*/
public function getRelationExistenceQueryForSelfRelation(Builder $query, Builder $parentQuery, $columns = ['*'])
{
$query->from($query->getModel()->getTable().' as '.$hash = $this->getRelationCountHash());
$hash = $this->getRelationCountHash();

$query->from($query->getModel()->getTable().' as '.$hash);

$this->performJoin($query);

Expand Down
15 changes: 15 additions & 0 deletions tests/HasManyDeepTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Tests\Models\RoleUser;
use Tests\Models\Tag;
use Tests\Models\User;
use Tests\Models\UserWithAliasTrait;

class HasManyDeepTest extends TestCase
{
Expand Down Expand Up @@ -174,6 +175,20 @@ public function testExistenceQueryForSelfRelationWithLeadingMorphMany()
$this->assertEquals([21, 23], $posts->pluck('id')->all());
}

public function testExistenceQueryForThroughSelfRelation()
{
$users = UserWithAliasTrait::withCount('teamPosts')->get();

$this->assertEquals([2, 2, 1], $users->pluck('team_posts_count')->all());
}

public function testExistenceQueryForThroughSelfRelationWithoutAliasTrait()
{
$this->expectExceptionMessageMatches('/' . preg_quote(User::class) . '/');

User::withCount('teamPosts')->get();
}

public function testPaginate()
{
$comments = Country::first()->comments()
Expand Down
5 changes: 5 additions & 0 deletions tests/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,9 @@ public function tagsFromRelations()
{
return $this->hasManyDeepFromRelations($this->posts(), (new Post())->tags());
}

public function teamPosts()
{
return $this->hasManyDeep(Post::class, [Team::class, static::class], ['id', null, 'user_id'], ['team_id']);
}
}
12 changes: 12 additions & 0 deletions tests/Models/UserWithAliasTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Tests\Models;

use Staudenmeir\EloquentHasManyDeep\HasTableAlias;

class UserWithAliasTrait extends User
{
use HasTableAlias;

protected $table = 'users';
}

0 comments on commit 658ad96

Please sign in to comment.