Skip to content

Commit

Permalink
Fixing multiple joins on the same relation using ->as()
Browse files Browse the repository at this point in the history
  • Loading branch information
luisdalmolin committed Feb 15, 2022
1 parent 742f6ac commit 99b126c
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 5 deletions.
22 changes: 22 additions & 0 deletions src/FakeJoinCallback.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace Kirschbaum\PowerJoins;

class FakeJoinCallback
{
protected $alias = null;

public function getAlias(): ?string
{
return $this->alias;
}

public function __call($name, $arguments)
{
if ($name === 'as') {
$this->alias = $arguments[0];
}

return $this;
}
}
35 changes: 30 additions & 5 deletions src/PowerJoins.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Illuminate\Support\Str;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Query\Expression;
use Kirschbaum\PowerJoins\FakeJoinCallback;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;

Expand Down Expand Up @@ -53,15 +54,19 @@ public function scopeJoinRelationship(Builder $query, $relationName, $callback =
return;
}

$relationQuery = $query->getModel()->{$relationName}()->getQuery();
$relationJoinCache = "{$relationQuery->getModel()->getTable()}.{$relationName}";
$relation = $query->getModel()->{$relationName}();
$relationQuery = $relation->getQuery();
$alias = $this->getAliasName($useAlias, $relation, $relationName, $callback);
$aliasString = is_array($alias) ? implode('.', $alias) : $alias;

$relationJoinCache = $alias
? "{$aliasString}.{$relationQuery->getModel()->getTable()}.{$relationName}"
: "{$relationQuery->getModel()->getTable()}.{$relationName}";

if ($this->relationshipAlreadyJoined($relationJoinCache)) {
return;
}

$relation = $query->getModel()->{$relationName}();
$alias = $useAlias ? $this->generateAliasForRelationship($relation, $relationName) : null;
$relation->performJoinForEloquentPowerJoins($query, $joinType, $callback, $alias, $disableExtraConditions);

$this->markRelationshipAsAlreadyJoined($relationJoinCache);
Expand Down Expand Up @@ -200,7 +205,6 @@ public function scopeOrderByPowerJoins(Builder $query, $sort, $direction = 'asc'
->orderBy(sprintf('%s_aggregation', $latestRelationshipName), $direction);
} else {
if ($column instanceof Expression) {
// dd($column);
$query->orderBy($column, $direction);
} else {
$query->orderBy(
Expand Down Expand Up @@ -405,4 +409,25 @@ protected function formatJoinCallback(string $relationName, $callback)

return $callback;
}

/**
* Get the join alias name from all the different options.
*/
protected function getAliasName($useAlias, $relation, $relationName, $callback)
{
if ($callback) {
if (is_callable($callback)) {
$fakeJoinCallback = new FakeJoinCallback();
$callback($fakeJoinCallback);

if ($fakeJoinCallback->getAlias()) {
return $fakeJoinCallback->getAlias();
}
}
}

return $useAlias
? $this->generateAliasForRelationship($relation, $relationName)
: null;
}
}
38 changes: 38 additions & 0 deletions tests/JoinRelationshipTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -576,4 +576,42 @@ public function test_nested_join_with_aliases()
])
->get();
}

/** @test */
public function test_join_same_relationship_using_named_alias()
{
$query = Post::query()
->where('posts.id', '>', 10)
->joinRelationship('category', function ($join) {
$join->as('category_1');
})
->joinRelationship('category', function ($join) {
$join->as('category_2');
})
->toSql();

$this->assertStringContainsString('inner join "categories" as "category_1" on "posts"."category_id" = "category_1"."id"', $query);
$this->assertStringContainsString('inner join "categories" as "category_2" on "posts"."category_id" = "category_2"."id"', $query);
}

/** @test */
public function test_join_same_nested_relationship_using_named_alias()
{
$this->markTestSkipped('Still to implement this using the array syntax');

$query = Post::query()
->where('posts.id', '>', 10)
->joinRelationship('category.parent', [
'category' => fn ($join) => $join->as('category_alias_1'),
'parent' => fn ($join) => $join->as('parent_alias_1'),
])
->joinRelationship('category.parent', [
'category' => fn ($join) => $join->as('category_alias_2'),
'parent' => fn ($join) => $join->as('parent_alias_2'),
])
->toSql();

$this->assertStringContainsString('inner join "categories" as "category_alias_1" on "posts"."category_id" = "category_alias_1"."id"', $query);
$this->assertStringContainsString('inner join "categories" as "category_alias_2" on "posts"."category_id" = "category_alias_2"."id"', $query);
}
}

0 comments on commit 99b126c

Please sign in to comment.