Skip to content

Commit 15411d0

Browse files
committed
wip
1 parent d73176f commit 15411d0

File tree

9 files changed

+163
-146
lines changed

9 files changed

+163
-146
lines changed

packages/database/src/BelongsTo.php

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Tempest\Database;
66

77
use Attribute;
8+
use Tempest\Database\Builder\ModelInspector;
89
use Tempest\Database\QueryStatements\FieldStatement;
910
use Tempest\Database\QueryStatements\JoinStatement;
1011
use Tempest\Reflection\PropertyReflector;
@@ -17,8 +18,8 @@ final class BelongsTo implements Relation
1718
public PropertyReflector $property;
1819

1920
public function __construct(
20-
public ?string $relationJoin = null,
21-
public ?string $ownerJoin = null,
21+
private readonly ?string $relationJoin = null,
22+
private readonly ?string $ownerJoin = null,
2223
) {}
2324

2425
public function getOwnerFieldName(): string
@@ -44,37 +45,61 @@ public function getSelectFields(): ImmutableArray
4445
public function getJoinStatement(): JoinStatement
4546
{
4647
$relationModel = model($this->property->getType()->asClass());
48+
$ownerModel = model($this->property->getClass());
4749

48-
// authors.id
50+
$relationJoin = $this->getRelationJoin($relationModel);
51+
$ownerJoin = $this->getOwnerJoin($ownerModel);
52+
53+
// LEFT JOIN authors ON authors.id = books.author_id
54+
return new JoinStatement(sprintf(
55+
'LEFT JOIN %s ON %s = %s',
56+
$relationModel->getTableName(),
57+
$relationJoin,
58+
$ownerJoin,
59+
));
60+
}
61+
62+
private function getRelationJoin(ModelInspector $relationModel): string
63+
{
4964
$relationJoin = $this->relationJoin;
5065

51-
if (! $relationJoin) {
52-
$relationJoin = sprintf(
53-
'%s.%s',
66+
if ($relationJoin && ! strpos($relationJoin, '.')) {
67+
$relationJoin = sprintf('%s.%s',
5468
$relationModel->getTableName(),
55-
$relationModel->getPrimaryKey(),
69+
$relationJoin,
5670
);
5771
}
5872

59-
// books.author_id
60-
$ownerJoin = $this->ownerJoin;
73+
if ($relationJoin) {
74+
return $relationJoin;
75+
}
6176

62-
if (! $ownerJoin) {
63-
$ownerModel = model($this->property->getClass());
77+
return sprintf(
78+
'%s.%s',
79+
$relationModel->getTableName(),
80+
$relationModel->getPrimaryKey(),
81+
);
82+
}
83+
84+
private function getOwnerJoin(ModelInspector $ownerModel): string
85+
{
86+
$ownerJoin = $this->ownerJoin;
6487

65-
$ownerJoin = sprintf(
66-
'%s.%s',
88+
if ($ownerJoin && ! strpos($ownerJoin, '.')) {
89+
$ownerJoin = sprintf('%s.%s',
6790
$ownerModel->getTableName(),
68-
$this->getOwnerFieldName(),
91+
$ownerJoin,
6992
);
7093
}
7194

72-
// LEFT JOIN authors ON authors.id = books.author_id
73-
return new JoinStatement(sprintf(
74-
'LEFT JOIN %s ON %s = %s',
75-
$relationModel->getTableName(),
76-
$relationJoin,
77-
$ownerJoin,
78-
));
95+
if ($ownerJoin) {
96+
return $ownerJoin;
97+
}
98+
99+
return sprintf(
100+
'%s.%s',
101+
$ownerModel->getTableName(),
102+
$this->getOwnerFieldName(),
103+
);
79104
}
80105
}

packages/database/src/Builder/ModelDefinition.php

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -82,39 +82,6 @@ public function getRelations(string $relationName): array
8282
return $relations;
8383
}
8484

85-
/** @return \Tempest\Database\Builder\Relations\Relation[] */
86-
public function getEagerRelations(): array
87-
{
88-
$relations = [];
89-
90-
foreach ($this->buildEagerRelationNames($this->modelClass) as $relationName) {
91-
foreach ($this->getRelations($relationName) as $relation) {
92-
$relations[$relation->getRelationName()] = $relation;
93-
}
94-
}
95-
96-
return $relations;
97-
}
98-
99-
private function buildEagerRelationNames(ClassReflector $class): array
100-
{
101-
$relations = [];
102-
103-
foreach ($class->getPublicProperties() as $property) {
104-
if (! $property->hasAttribute(Eager::class)) {
105-
continue;
106-
}
107-
108-
$relations[] = $property->getName();
109-
110-
foreach ($this->buildEagerRelationNames($property->getType()->asClass()) as $childRelation) {
111-
$relations[] = "{$property->getName()}.{$childRelation}";
112-
}
113-
}
114-
115-
return $relations;
116-
}
117-
11885
public function getTableDefinition(): TableDefinition
11986
{
12087
$specificName = $this->modelClass

packages/database/src/Exceptions/InvalidRelation.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Exception;
88

9+
// TODO remove
910
final class InvalidRelation extends Exception
1011
{
1112
public static function inversePropertyNotFound(string $modelClass, string $modelProperty, string $relatedClass): self
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
3+
namespace Integration\Database;
4+
5+
use Tempest\Database\BelongsTo;
6+
use Tempest\Database\Config\DatabaseDialect;
7+
use Tests\Tempest\Integration\Database\Relations\Fixtures\BelongsToOwnerModel;
8+
use Tests\Tempest\Integration\FrameworkIntegrationTestCase;
9+
use function Tempest\Database\model;
10+
11+
final class BelongsToTest extends FrameworkIntegrationTestCase
12+
{
13+
public function test_belongs_to(): void
14+
{
15+
$model = model(BelongsToOwnerModel::class);
16+
$relation = $model->getRelation('relatedModel');
17+
18+
$this->assertInstanceOf(BelongsTo::class, $relation);
19+
20+
$this->assertEquals(
21+
'LEFT JOIN relation ON relation.id = owner.relation_id',
22+
$relation->getJoinStatement()->compile(DatabaseDialect::SQLITE),
23+
);
24+
}
25+
26+
public function test_belongs_to_with_relation_join_field(): void
27+
{
28+
$model = model(BelongsToOwnerModel::class);
29+
$relation = $model->getRelation('relationJoinField');
30+
31+
$this->assertInstanceOf(BelongsTo::class, $relation);
32+
33+
$this->assertEquals(
34+
'LEFT JOIN relation ON relation.overwritten_id = owner.relation_id',
35+
$relation->getJoinStatement()->compile(DatabaseDialect::SQLITE),
36+
);
37+
}
38+
39+
public function test_belongs_to_with_relation_join_field_and_table(): void
40+
{
41+
$model = model(BelongsToOwnerModel::class);
42+
$relation = $model->getRelation('relationJoinFieldAndTable');
43+
44+
$this->assertInstanceOf(BelongsTo::class, $relation);
45+
46+
$this->assertEquals(
47+
'LEFT JOIN relation ON overwritten.overwritten_id = owner.relation_id',
48+
$relation->getJoinStatement()->compile(DatabaseDialect::SQLITE),
49+
);
50+
}
51+
52+
public function test_belongs_to_with_owner_join_field(): void
53+
{
54+
$model = model(BelongsToOwnerModel::class);
55+
$relation = $model->getRelation('ownerJoinField');
56+
57+
$this->assertInstanceOf(BelongsTo::class, $relation);
58+
59+
$this->assertEquals(
60+
'LEFT JOIN relation ON relation.id = owner.overwritten_id',
61+
$relation->getJoinStatement()->compile(DatabaseDialect::SQLITE),
62+
);
63+
}
64+
65+
public function test_belongs_to_with_owner_join_field_and_table(): void
66+
{
67+
$model = model(BelongsToOwnerModel::class);
68+
$relation = $model->getRelation('ownerJoinFieldAndTable');
69+
70+
$this->assertInstanceOf(BelongsTo::class, $relation);
71+
72+
$this->assertEquals(
73+
'LEFT JOIN relation ON relation.id = overwritten.overwritten_id',
74+
$relation->getJoinStatement()->compile(DatabaseDialect::SQLITE),
75+
);
76+
}
77+
}

tests/Integration/Database/Relations/BelongsToRelationTest.php

Lines changed: 0 additions & 59 deletions
This file was deleted.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Tempest\Integration\Database\Relations\Fixtures;
6+
7+
use Tempest\Database\BelongsTo;
8+
use Tempest\Database\IsDatabaseModel;
9+
use Tempest\Database\Table;
10+
11+
#[Table('owner')]
12+
final class BelongsToOwnerModel
13+
{
14+
use IsDatabaseModel;
15+
16+
public BelongsToRelationModel $relatedModel;
17+
18+
#[BelongsTo(relationJoin: 'overwritten_id')]
19+
public BelongsToRelationModel $relationJoinField;
20+
21+
#[BelongsTo(relationJoin: 'overwritten.overwritten_id')]
22+
public BelongsToRelationModel $relationJoinFieldAndTable;
23+
24+
#[BelongsTo(ownerJoin: 'overwritten_id')]
25+
public BelongsToRelationModel $ownerJoinField;
26+
27+
#[BelongsTo(ownerJoin: 'overwritten.overwritten_id')]
28+
public BelongsToRelationModel $ownerJoinFieldAndTable;
29+
}

tests/Integration/Database/Relations/Fixtures/BelongsToParentModel.php

Lines changed: 0 additions & 23 deletions
This file was deleted.

tests/Integration/Database/Relations/Fixtures/BelongsToRelatedModel.php renamed to tests/Integration/Database/Relations/Fixtures/BelongsToRelationModel.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,19 @@
88
use Tempest\Database\IsDatabaseModel;
99
use Tempest\Database\Table;
1010

11-
#[Table('belongs_to_related')]
12-
final class BelongsToRelatedModel
11+
#[Table('relation')]
12+
final class BelongsToRelationModel
1313
{
1414
use IsDatabaseModel;
1515

16-
/** @var \Tests\Tempest\Integration\Database\Relations\Fixtures\BelongsToParentModel[] */
16+
/** @var \Tests\Tempest\Integration\Database\Relations\Fixtures\BelongsToOwnerModel[] */
1717
public array $inferred = [];
1818

1919
#[HasMany('other_id')]
20-
/** @var \Tests\Tempest\Integration\Database\Relations\Fixtures\BelongsToParentModel[] */
20+
/** @var \Tests\Tempest\Integration\Database\Relations\Fixtures\BelongsToOwnerModel[] */
2121
public array $attribute = [];
2222

23-
#[HasMany('other_id', BelongsToParentModel::class, 'other_id')]
23+
#[HasMany('other_id', BelongsToOwnerModel::class, 'other_id')]
2424
public array $full = [];
2525

2626
/** @var \Tests\Tempest\Integration\Database\Relations\Fixtures\HasOneParentModel[] */

0 commit comments

Comments
 (0)