Skip to content

Commit 317d40a

Browse files
committed
wip
1 parent 15411d0 commit 317d40a

15 files changed

+331
-280
lines changed

packages/database/src/HasMany.php

Lines changed: 48 additions & 25 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;
@@ -16,13 +17,9 @@ final class HasMany implements Relation
1617
{
1718
public PropertyReflector $property;
1819

19-
public string $fieldName {
20-
get => $this->property->getName() . '.' . $this->localPropertyName;
21-
}
22-
2320
public function __construct(
24-
public ?string $relationJoin = null,
2521
public ?string $ownerJoin = null,
22+
public ?string $relationJoin = null,
2623
) {}
2724

2825
public function getSelectFields(): ImmutableArray
@@ -47,37 +44,63 @@ public function idField(): string
4744

4845
public function getJoinStatement(): JoinStatement
4946
{
50-
$relationModel = model($this->property->getIterableType()->asClass());
51-
$ownerModel = model($this->property->getClass());
47+
$ownerModel = model($this->property->getIterableType()->asClass());
48+
$relationModel = model($this->property->getClass());
5249

53-
// chapters.book_id
54-
$relationJoin = $this->relationJoin;
50+
$ownerJoin = $this->getOwnerJoin($ownerModel, $relationModel);
51+
$relationJoin = $this->getRelationJoin($relationModel);
5552

56-
if (! $relationJoin) {
57-
$relationJoin = sprintf(
58-
'%s.%s',
59-
$relationModel->getTableName(),
60-
str($ownerModel->getTableName())->singularizeLastWord() . '_' . $ownerModel->getPrimaryKey(),
61-
);
62-
}
53+
return new JoinStatement(sprintf(
54+
'LEFT JOIN %s ON %s = %s',
55+
$ownerModel->getTableName(),
56+
$ownerJoin,
57+
$relationJoin,
58+
));
59+
}
6360

64-
// books.id
61+
private function getOwnerJoin(ModelInspector $ownerModel, ModelInspector $relationModel): string
62+
{
6563
$ownerJoin = $this->ownerJoin;
6664

67-
if (! $ownerJoin) {
65+
if ($ownerJoin && ! strpos($ownerJoin, '.')) {
6866
$ownerJoin = sprintf(
6967
'%s.%s',
7068
$ownerModel->getTableName(),
71-
$ownerModel->getPrimaryKey(),
69+
$ownerJoin,
7270
);
7371
}
7472

75-
// LEFT JOIN chapters ON chapters.book_id = books.id
76-
return new JoinStatement(sprintf(
77-
'LEFT JOIN %s ON %s = %s',
73+
if ($ownerJoin) {
74+
return $ownerJoin;
75+
}
76+
77+
return sprintf(
78+
'%s.%s',
79+
$ownerModel->getTableName(),
80+
str($relationModel->getTableName())->singularizeLastWord() . '_' . $relationModel->getPrimaryKey(),
81+
);
82+
}
83+
84+
private function getRelationJoin(ModelInspector $relationModel): string
85+
{
86+
$relationJoin = $this->relationJoin;
87+
88+
if ($relationJoin && ! strpos($relationJoin, '.')) {
89+
$relationJoin = sprintf(
90+
'%s.%s',
91+
$relationModel->getTableName(),
92+
$relationJoin,
93+
);
94+
}
95+
96+
if ($relationJoin) {
97+
return $relationJoin;
98+
}
99+
100+
return sprintf(
101+
'%s.%s',
78102
$relationModel->getTableName(),
79-
$relationJoin,
80-
$ownerJoin,
81-
));
103+
$relationModel->getPrimaryKey(),
104+
);
82105
}
83106
}

packages/database/src/HasOne.php

Lines changed: 48 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 HasOne implements Relation
1718
public PropertyReflector $property;
1819

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

2425
public function getSelectFields(): ImmutableArray
@@ -32,37 +33,63 @@ public function getSelectFields(): ImmutableArray
3233

3334
public function getJoinStatement(): JoinStatement
3435
{
35-
$relationModel = model($this->property->getType()->asClass());
36-
$ownerModel = model($this->property->getClass());
36+
$ownerModel = model($this->property->getType()->asClass());
37+
$relationModel = model($this->property->getClass());
3738

38-
// isbns.book_id
39-
$relationJoin = $this->relationJoin;
39+
$ownerJoin = $this->getOwnerJoin($ownerModel, $relationModel);
40+
$relationJoin = $this->getRelationJoin($relationModel);
4041

41-
if (! $relationJoin) {
42-
$relationJoin = sprintf(
43-
'%s.%s',
44-
$relationModel->getTableName(),
45-
str($ownerModel->getTableName())->singularizeLastWord() . '_' . $ownerModel->getPrimaryKey(),
46-
);
47-
}
42+
return new JoinStatement(sprintf(
43+
'LEFT JOIN %s ON %s = %s',
44+
$ownerModel->getTableName(),
45+
$ownerJoin,
46+
$relationJoin,
47+
));
48+
}
4849

49-
// books.id
50+
private function getOwnerJoin(ModelInspector $ownerModel, ModelInspector $relationModel): string
51+
{
5052
$ownerJoin = $this->ownerJoin;
5153

52-
if (! $ownerJoin) {
54+
if ($ownerJoin && ! strpos($ownerJoin, '.')) {
5355
$ownerJoin = sprintf(
5456
'%s.%s',
5557
$ownerModel->getTableName(),
56-
$ownerModel->getPrimaryKey(),
58+
$ownerJoin,
5759
);
5860
}
5961

60-
// LEFT JOIN isbn ON isbns.book_id = books.id
61-
return new JoinStatement(sprintf(
62-
'LEFT JOIN %s ON %s = %s',
62+
if ($ownerJoin) {
63+
return $ownerJoin;
64+
}
65+
66+
return sprintf(
67+
'%s.%s',
68+
$ownerModel->getTableName(),
69+
str($relationModel->getTableName())->singularizeLastWord() . '_' . $relationModel->getPrimaryKey(),
70+
);
71+
}
72+
73+
private function getRelationJoin(ModelInspector $relationModel): string
74+
{
75+
$relationJoin = $this->relationJoin;
76+
77+
if ($relationJoin && ! strpos($relationJoin, '.')) {
78+
$relationJoin = sprintf(
79+
'%s.%s',
80+
$relationModel->getTableName(),
81+
$relationJoin,
82+
);
83+
}
84+
85+
if ($relationJoin) {
86+
return $relationJoin;
87+
}
88+
89+
return sprintf(
90+
'%s.%s',
6391
$relationModel->getTableName(),
64-
$relationJoin,
65-
$ownerJoin,
66-
));
92+
$relationModel->getPrimaryKey(),
93+
);
6794
}
6895
}

tests/Integration/Database/BelongsToTest.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@
44

55
use Tempest\Database\BelongsTo;
66
use Tempest\Database\Config\DatabaseDialect;
7-
use Tests\Tempest\Integration\Database\Relations\Fixtures\BelongsToOwnerModel;
7+
use Tests\Tempest\Integration\Database\Fixtures\OwnerModel;
88
use Tests\Tempest\Integration\FrameworkIntegrationTestCase;
99
use function Tempest\Database\model;
1010

1111
final class BelongsToTest extends FrameworkIntegrationTestCase
1212
{
1313
public function test_belongs_to(): void
1414
{
15-
$model = model(BelongsToOwnerModel::class);
16-
$relation = $model->getRelation('relatedModel');
15+
$model = model(OwnerModel::class);
16+
$relation = $model->getRelation('relation');
1717

1818
$this->assertInstanceOf(BelongsTo::class, $relation);
1919

@@ -25,7 +25,7 @@ public function test_belongs_to(): void
2525

2626
public function test_belongs_to_with_relation_join_field(): void
2727
{
28-
$model = model(BelongsToOwnerModel::class);
28+
$model = model(OwnerModel::class);
2929
$relation = $model->getRelation('relationJoinField');
3030

3131
$this->assertInstanceOf(BelongsTo::class, $relation);
@@ -38,7 +38,7 @@ public function test_belongs_to_with_relation_join_field(): void
3838

3939
public function test_belongs_to_with_relation_join_field_and_table(): void
4040
{
41-
$model = model(BelongsToOwnerModel::class);
41+
$model = model(OwnerModel::class);
4242
$relation = $model->getRelation('relationJoinFieldAndTable');
4343

4444
$this->assertInstanceOf(BelongsTo::class, $relation);
@@ -51,7 +51,7 @@ public function test_belongs_to_with_relation_join_field_and_table(): void
5151

5252
public function test_belongs_to_with_owner_join_field(): void
5353
{
54-
$model = model(BelongsToOwnerModel::class);
54+
$model = model(OwnerModel::class);
5555
$relation = $model->getRelation('ownerJoinField');
5656

5757
$this->assertInstanceOf(BelongsTo::class, $relation);
@@ -64,7 +64,7 @@ public function test_belongs_to_with_owner_join_field(): void
6464

6565
public function test_belongs_to_with_owner_join_field_and_table(): void
6666
{
67-
$model = model(BelongsToOwnerModel::class);
67+
$model = model(OwnerModel::class);
6868
$relation = $model->getRelation('ownerJoinFieldAndTable');
6969

7070
$this->assertInstanceOf(BelongsTo::class, $relation);
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Tempest\Integration\Database\Fixtures;
6+
7+
use Tempest\Database\HasOne;
8+
use Tempest\Database\Table;
9+
10+
#[Table('relation')]
11+
final class HasOneRelationModel
12+
{
13+
#[HasOne]
14+
public OwnerModel $owner;
15+
16+
#[HasOne(ownerJoin: 'overwritten_id')]
17+
public OwnerModel $ownerJoinField;
18+
19+
#[HasOne(ownerJoin: 'overwritten.overwritten_id')]
20+
public OwnerModel $ownerJoinFieldAndTable;
21+
22+
#[HasOne(relationJoin: 'overwritten_id')]
23+
public OwnerModel $relationJoinField;
24+
25+
#[HasOne(relationJoin: 'overwritten.overwritten_id')]
26+
public OwnerModel $relationJoinFieldAndTable;
27+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Tempest\Integration\Database\Fixtures;
6+
7+
use Tempest\Database\BelongsTo;
8+
use Tempest\Database\Table;
9+
10+
#[Table('owner')]
11+
final class OwnerModel
12+
{
13+
public RelationModel $relation;
14+
15+
#[BelongsTo(relationJoin: 'overwritten_id')]
16+
public RelationModel $relationJoinField;
17+
18+
#[BelongsTo(relationJoin: 'overwritten.overwritten_id')]
19+
public RelationModel $relationJoinFieldAndTable;
20+
21+
#[BelongsTo(ownerJoin: 'overwritten_id')]
22+
public RelationModel $ownerJoinField;
23+
24+
#[BelongsTo(ownerJoin: 'overwritten.overwritten_id')]
25+
public RelationModel $ownerJoinFieldAndTable;
26+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Tempest\Integration\Database\Fixtures;
6+
7+
use Tempest\Database\HasMany;
8+
use Tempest\Database\Table;
9+
10+
#[Table('relation')]
11+
final class RelationModel
12+
{
13+
/** @var \Tests\Tempest\Integration\Database\Fixtures\OwnerModel[] */
14+
public array $owners = [];
15+
16+
/** @var \Tests\Tempest\Integration\Database\Fixtures\OwnerModel[] */
17+
#[HasMany(ownerJoin: 'overwritten_id')]
18+
public array $ownerJoinField = [];
19+
20+
/** @var \Tests\Tempest\Integration\Database\Fixtures\OwnerModel[] */
21+
#[HasMany(ownerJoin: 'overwritten.overwritten_id')]
22+
public array $ownerJoinFieldAndTable = [];
23+
24+
/** @var \Tests\Tempest\Integration\Database\Fixtures\OwnerModel[] */
25+
#[HasMany(relationJoin: 'overwritten_id')]
26+
public array $relationJoinField = [];
27+
28+
/** @var \Tests\Tempest\Integration\Database\Fixtures\OwnerModel[] */
29+
#[HasMany(relationJoin: 'overwritten.overwritten_id')]
30+
public array $relationJoinFieldAndTable = [];
31+
}

0 commit comments

Comments
 (0)