Skip to content
21 changes: 16 additions & 5 deletions packages/database/src/BelongsTo.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#[Attribute(Attribute::TARGET_PROPERTY)]
final class BelongsTo implements Relation
{
use HasTableAlias;

public PropertyReflector $property;

public string $name {
Expand Down Expand Up @@ -62,7 +64,7 @@ public function getSelectFields(): ImmutableArray
$relationModel = inspect($this->property->getType()->asClass());
$tableReference = $this->isSelfReferencing()
? $this->property->getName()
: $relationModel->getTableName();
: $this->getTableAlias($relationModel->getTableName());

return $relationModel
->getSelectFields()
Expand All @@ -79,8 +81,12 @@ public function getJoinStatement(): JoinStatement
{
$relationModel = inspect($this->property->getType()->asClass());
$ownerModel = inspect($this->property->getClass());
$tableAlias = $this->getTableAlias($relationModel->getTableName());

$relationJoin = $this->getRelationJoin($relationModel);
$relationJoin = $this->getRelationJoin(
relationModel: $relationModel,
tableAlias: $tableAlias,
);
$ownerJoin = $this->getOwnerJoin($ownerModel);

if ($this->isSelfReferencing()) {
Expand All @@ -93,21 +99,26 @@ public function getJoinStatement(): JoinStatement
));
}

$tableName = $relationModel->getTableName();
$tableRef = $tableAlias !== $tableName
? sprintf('%s AS %s', $tableName, $tableAlias)
: $tableName;

// LEFT JOIN authors ON authors.id = books.author_id
return new JoinStatement(sprintf(
'LEFT JOIN %s ON %s = %s',
$relationModel->getTableName(),
$tableRef,
$relationJoin,
$ownerJoin,
));
}

private function getRelationJoin(ModelInspector $relationModel): string
private function getRelationJoin(ModelInspector $relationModel, string $tableAlias): string
{
$relationJoin = $this->relationJoin;
$tableReference = $this->isSelfReferencing()
? $this->property->getName()
: $relationModel->getTableName();
: $tableAlias;

if ($relationJoin && ! strpos($relationJoin, '.')) {
$relationJoin = sprintf('%s.%s', $tableReference, $relationJoin);
Expand Down
25 changes: 18 additions & 7 deletions packages/database/src/BelongsToMany.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#[Attribute(flags: Attribute::TARGET_PROPERTY)]
final class BelongsToMany implements Relation
{
use HasTableAlias;

public PropertyReflector $property;

public string $name {
Expand Down Expand Up @@ -54,7 +56,7 @@ public function getSelectFields(): ImmutableArray
->map(map: fn (
$field,
) => new FieldStatement(
field: $targetModel->getTableName() . '.' . $field,
field: "{$this->getTableAlias(tableName: $targetModel->getTableName())}.{$field}",
)
->withAlias(
alias: sprintf(
Expand Down Expand Up @@ -120,7 +122,6 @@ public function getJoinStatement(): JoinStatement
ownerModel: $ownerModel,
targetModel: $targetModel,
);

return new JoinStatement(
statement: sprintf(
'%s %s',
Expand All @@ -131,6 +132,7 @@ public function getJoinStatement(): JoinStatement
$this->buildSecondJoin(
targetModel: $targetModel,
pivotTable: $pivotTable,
tableAlias: $this->getTableAlias(tableName: $targetModel->getTableName()),
),
),
);
Expand Down Expand Up @@ -174,11 +176,20 @@ private function buildFirstJoin(
private function buildSecondJoin(
ModelInspector $targetModel,
string $pivotTable,
string $tableAlias,
): string {
$tableName = $targetModel->getTableName();
$tableRef = $tableAlias !== $tableName
? sprintf('%s AS %s', $tableName, $tableAlias)
: $tableName;

return sprintf(
'LEFT JOIN %s ON %s = %s',
$targetModel->getTableName(),
$this->resolveRelatedRelationJoin(targetModel: $targetModel),
$tableRef,
$this->resolveRelatedRelationJoin(
targetModel: $targetModel,
tableAlias: $tableAlias,
),
$this->resolveRelatedOwnerJoin(
targetModel: $targetModel,
pivotTable: $pivotTable,
Expand Down Expand Up @@ -316,7 +327,7 @@ private function resolveRelatedOwnerJoin(
/**
* PK on target: target.id
*/
private function resolveRelatedRelationJoin(ModelInspector $targetModel): string
private function resolveRelatedRelationJoin(ModelInspector $targetModel, string $tableAlias): string
{
$relatedRelationJoin = $this->relatedRelationJoin;

Expand All @@ -329,7 +340,7 @@ private function resolveRelatedRelationJoin(ModelInspector $targetModel): string
) {
return sprintf(
'%s.%s',
$targetModel->getTableName(),
$tableAlias,
$relatedRelationJoin,
);
}
Expand All @@ -349,7 +360,7 @@ private function resolveRelatedRelationJoin(ModelInspector $targetModel): string

return sprintf(
'%s.%s',
$targetModel->getTableName(),
$tableAlias,
$primaryKey,
);
}
Expand Down
13 changes: 10 additions & 3 deletions packages/database/src/Builder/ModelInspector.php
Original file line number Diff line number Diff line change
Expand Up @@ -606,8 +606,12 @@ public function resolveRelations(string $relationString, string $parent = '', ar
$relationModel = inspect($currentRelation);
$modelType = $relationModel->getName();

$fullPath = $parent !== ''
? "{$parent}.{$currentRelationName}"
: $currentRelationName;

if (in_array($modelType, $visitedPaths, true)) {
return [$currentRelationName => $currentRelation->setParent($parent)];
return [$fullPath => $currentRelation->setParent($parent)];
}

$newRelationString = implode('.', $relationNames);
Expand All @@ -618,7 +622,7 @@ public function resolveRelations(string $relationString, string $parent = '', ar
$currentRelationName,
), '.');

$relations = [$currentRelationName => $currentRelation];
$relations = [$fullPath => $currentRelation];

return [
...$relations,
Expand Down Expand Up @@ -659,7 +663,10 @@ public function resolveEagerRelations(string $parent = '', array $visitedPaths =
continue;
}

$relations[$property->getName()] = $currentRelation->setParent($parent);
$fullPath = $parent !== ''
? "{$parent}.{$currentRelationName}"
: $currentRelationName;
$relations[$fullPath] = $currentRelation->setParent($parent);
$newVisitedPaths = [...$visitedPaths, $this->getName()];

foreach ($relationModel->resolveEagerRelations($newParent, $newVisitedPaths) as $name => $nestedEagerRelation) {
Expand Down
22 changes: 17 additions & 5 deletions packages/database/src/HasMany.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#[Attribute(Attribute::TARGET_PROPERTY)]
final class HasMany implements Relation
{
use HasTableAlias;

public PropertyReflector $property;

public string $name {
Expand All @@ -42,7 +44,7 @@ public function getSelectFields(): ImmutableArray
$relationModel = inspect($this->property->getIterableType()->asClass());
$tableReference = $this->isSelfReferencing()
? $this->property->getName()
: $relationModel->getTableName();
: $this->getTableAlias($relationModel->getTableName());

return $relationModel
->getSelectFields()
Expand Down Expand Up @@ -87,8 +89,13 @@ public function getJoinStatement(): JoinStatement
{
$ownerModel = inspect($this->property->getIterableType()->asClass());
$relationModel = inspect($this->property->getClass());
$tableAlias = $this->getTableAlias($ownerModel->getTableName());

$ownerJoin = $this->getOwnerJoin($ownerModel, $relationModel);
$ownerJoin = $this->getOwnerJoin(
ownerModel: $ownerModel,
relationModel: $relationModel,
tableAlias: $tableAlias,
);
$relationJoin = $this->getRelationJoin($relationModel);

if ($this->isSelfReferencing()) {
Expand All @@ -101,20 +108,25 @@ public function getJoinStatement(): JoinStatement
));
}

$tableName = $ownerModel->getTableName();
$tableRef = $tableAlias !== $tableName
? sprintf('%s AS %s', $tableName, $tableAlias)
: $tableName;

return new JoinStatement(sprintf(
'LEFT JOIN %s ON %s = %s',
$ownerModel->getTableName(),
$tableRef,
$ownerJoin,
$relationJoin,
));
}

private function getOwnerJoin(ModelInspector $ownerModel, ModelInspector $relationModel): string
private function getOwnerJoin(ModelInspector $ownerModel, ModelInspector $relationModel, string $tableAlias): string
{
$ownerJoin = $this->ownerJoin;
$tableReference = $this->isSelfReferencing()
? $this->property->getName()
: $ownerModel->getTableName();
: $tableAlias;

if ($ownerJoin && ! strpos($ownerJoin, '.')) {
$ownerJoin = sprintf(
Expand Down
18 changes: 14 additions & 4 deletions packages/database/src/HasManyThrough.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#[Attribute(flags: Attribute::TARGET_PROPERTY)]
final class HasManyThrough implements Relation
{
use HasTableAlias;

public PropertyReflector $property;

public string $name {
Expand Down Expand Up @@ -56,7 +58,7 @@ public function getSelectFields(): ImmutableArray
->map(map: fn (
$field,
) => new FieldStatement(
field: $targetModel->getTableName() . '.' . $field,
field: "{$this->getTableAlias(tableName: $targetModel->getTableName())}.{$field}",
)
->withAlias(
alias: sprintf(
Expand Down Expand Up @@ -152,12 +154,19 @@ private function buildSecondJoin(
ModelInspector $intermediateModel,
ModelInspector $targetModel,
): string {
$tableAlias = $this->getTableAlias(tableName: $targetModel->getTableName());
$tableName = $targetModel->getTableName();
$tableRef = $tableAlias !== $tableName
? sprintf('%s AS %s', $tableName, $tableAlias)
: $tableName;

return sprintf(
'LEFT JOIN %s ON %s = %s',
$targetModel->getTableName(),
$tableRef,
$this->resolveThroughOwnerJoin(
targetModel: $targetModel,
intermediateModel: $intermediateModel,
tableAlias: $tableAlias,
),
$this->resolveThroughRelationJoin(intermediateModel: $intermediateModel),
);
Expand Down Expand Up @@ -244,6 +253,7 @@ private function resolveRelationJoin(ModelInspector $ownerModel): string
private function resolveThroughOwnerJoin(
ModelInspector $targetModel,
ModelInspector $intermediateModel,
string $tableAlias,
): string {
$throughOwnerJoin = $this->throughOwnerJoin;

Expand All @@ -256,7 +266,7 @@ private function resolveThroughOwnerJoin(
) {
return sprintf(
'%s.%s',
$targetModel->getTableName(),
$tableAlias,
$throughOwnerJoin,
);
}
Expand All @@ -276,7 +286,7 @@ private function resolveThroughOwnerJoin(

return sprintf(
'%s.%s',
$targetModel->getTableName(),
$tableAlias,
str(string: $intermediateModel->getTableName())->singularizeLastWord() . '_' . $primaryKey,
);
}
Expand Down
22 changes: 17 additions & 5 deletions packages/database/src/HasOne.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#[Attribute(Attribute::TARGET_PROPERTY)]
final class HasOne implements Relation
{
use HasTableAlias;

public PropertyReflector $property;

public string $name {
Expand All @@ -42,7 +44,7 @@ public function getSelectFields(): ImmutableArray
$relationModel = inspect($this->property->getType()->asClass());
$tableReference = $this->isSelfReferencing()
? $this->property->getName()
: $relationModel->getTableName();
: $this->getTableAlias($relationModel->getTableName());

return $relationModel
->getSelectFields()
Expand All @@ -59,8 +61,13 @@ public function getJoinStatement(): JoinStatement
{
$ownerModel = inspect($this->property->getType()->asClass());
$relationModel = inspect($this->property->getClass());
$tableAlias = $this->getTableAlias($ownerModel->getTableName());

$ownerJoin = $this->getOwnerJoin($ownerModel, $relationModel);
$ownerJoin = $this->getOwnerJoin(
ownerModel: $ownerModel,
relationModel: $relationModel,
tableAlias: $tableAlias,
);
$relationJoin = $this->getRelationJoin($relationModel);

if ($this->isSelfReferencing()) {
Expand All @@ -73,20 +80,25 @@ public function getJoinStatement(): JoinStatement
));
}

$tableName = $ownerModel->getTableName();
$tableRef = $tableAlias !== $tableName
? sprintf('%s AS %s', $tableName, $tableAlias)
: $tableName;

return new JoinStatement(sprintf(
'LEFT JOIN %s ON %s = %s',
$ownerModel->getTableName(),
$tableRef,
$ownerJoin,
$relationJoin,
));
}

private function getOwnerJoin(ModelInspector $ownerModel, ModelInspector $relationModel): string
private function getOwnerJoin(ModelInspector $ownerModel, ModelInspector $relationModel, string $tableAlias): string
{
$ownerJoin = $this->ownerJoin;
$tableReference = $this->isSelfReferencing()
? $this->property->getName()
: $ownerModel->getTableName();
: $tableAlias;

if ($ownerJoin && ! strpos($ownerJoin, '.')) {
$ownerJoin = sprintf(
Expand Down
Loading
Loading