Skip to content

Commit d3a02ee

Browse files
committed
wip
1 parent 0b86c3d commit d3a02ee

File tree

3 files changed

+74
-7
lines changed

3 files changed

+74
-7
lines changed

packages/database/src/Mappers/SelectModelMapper.php

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,18 +54,26 @@ private function values(ModelInspector $model, array $data): array
5454
foreach ($data as $key => $value) {
5555
$relation = $model->getRelation($key);
5656

57-
if (! $relation instanceof HasMany) {
57+
if ($relation instanceof BelongsTo) {
58+
$relationModel = inspect($relation);
59+
60+
if (($data[$relation->name][$relationModel->getPrimaryKeyProperty()->getName()] ?? null) === null) {
61+
$data[$relation->name] = null;
62+
}
63+
5864
continue;
5965
}
6066

61-
$mapped = [];
62-
$relationModel = inspect($relation);
67+
if ($relation instanceof HasMany) {
68+
$mapped = [];
69+
$relationModel = inspect($relation);
6370

64-
foreach ($value as $item) {
65-
$mapped[] = $this->values($relationModel, $item);
66-
}
71+
foreach ($value as $item) {
72+
$mapped[] = $this->values($relationModel, $item);
73+
}
6774

68-
$data[$key] = $mapped;
75+
$data[$key] = $mapped;
76+
}
6977
}
7078

7179
return $data;

packages/mapper/src/Mappers/ArrayToObjectMapper.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@ public function resolveValue(PropertyReflector $property, mixed $value): mixed
154154
{
155155
$caster = $this->casterFactory->forProperty($property);
156156

157+
if ($property->isNullable() && $value === null) {
158+
return null;
159+
}
160+
157161
if ($caster === null) {
158162
return $value;
159163
}

tests/Integration/Database/Builder/IsDatabaseModelTest.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,21 @@ public function test_delete_nonexistent_record(): void
617617

618618
$this->assertNull(Foo::get($fooId));
619619
}
620+
621+
public function test_nullable_relations(): void
622+
{
623+
$this->migrate(
624+
CreateMigrationsTable::class,
625+
CreateANullableTable::class,
626+
CreateBNullableTable::class,
627+
);
628+
629+
$a = ANullableModel::create();
630+
631+
$a->load('b');
632+
633+
$this->assertNull($a->b);
634+
}
620635
}
621636

622637
final class Foo
@@ -963,3 +978,43 @@ public function up(): QueryStatement
963978
->text('description');
964979
}
965980
}
981+
982+
final class CreateANullableTable implements MigratesUp
983+
{
984+
private(set) string $name = '100-create-a-nullable';
985+
986+
public function up(): QueryStatement
987+
{
988+
return new CreateTableStatement('a')
989+
->primary()
990+
->belongsTo('a.b_id', 'b.id', nullable: true);
991+
}
992+
}
993+
994+
final class CreateBNullableTable implements MigratesUp
995+
{
996+
private(set) string $name = '100-create-b-nullable';
997+
998+
public function up(): QueryStatement
999+
{
1000+
return new CreateTableStatement('b')
1001+
->primary()
1002+
->string('name');
1003+
}
1004+
}
1005+
1006+
#[Table('a')]
1007+
final class ANullableModel
1008+
{
1009+
use IsDatabaseModel;
1010+
1011+
public ?BNullableModel $b = null;
1012+
}
1013+
1014+
#[Table('b')]
1015+
final class BNullableModel
1016+
{
1017+
use IsDatabaseModel;
1018+
1019+
public string $name;
1020+
}

0 commit comments

Comments
 (0)