Skip to content

Commit 6996a5f

Browse files
committed
fix(database): handle object serialization using insert
1 parent 1ddbc7c commit 6996a5f

File tree

3 files changed

+71
-2
lines changed

3 files changed

+71
-2
lines changed

packages/database/src/Builder/QueryBuilders/InsertQueryBuilder.php

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ private function resolveIterableData(iterable $model): array
323323
continue;
324324
}
325325

326-
$entry[$key] = $value;
326+
$entry[$key] = $this->serializeIterableValue($key, $value);
327327
}
328328

329329
return $entry;
@@ -447,4 +447,36 @@ private function serializeValue(PropertyReflector $property, mixed $value): mixe
447447

448448
return $this->serializerFactory->forProperty($property)?->serialize($value) ?? $value;
449449
}
450+
451+
private function serializeIterableValue(string $key, mixed $value): mixed
452+
{
453+
if ($value === null) {
454+
return null;
455+
}
456+
457+
// Booleans should be handled by the database layer, not by serializers
458+
if (is_bool($value)) {
459+
return $value;
460+
}
461+
462+
// Only serialize if we have an object model to work with
463+
if (! $this->model->isObjectModel()) {
464+
return $value;
465+
}
466+
467+
if (! $this->model?->reflector->hasProperty($key)) {
468+
return $value;
469+
}
470+
471+
$property = $this->model->reflector->getProperty($key);
472+
473+
if ($property->getType()->accepts(PrimaryKey::class)) {
474+
return $value;
475+
}
476+
477+
return $this->serializeValue(
478+
property: $property,
479+
value: $value,
480+
);
481+
}
450482
}

tests/Integration/Database/Builder/InsertQueryBuilderTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public function test_insert_on_model_table(): void
7171
$query = query(Author::class)
7272
->insert(
7373
$author,
74-
['name' => 'other name', 'type' => AuthorType::B->value, 'publisher_id' => null],
74+
['name' => 'other name', 'type' => AuthorType::B, 'publisher_id' => null],
7575
)
7676
->build();
7777

tests/Integration/Database/DtoSerialization/BasicDtoSerializationTest.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,43 @@ public function down(): null
5656
$this->assertSame(80, $retrievedCharacter->stats->mana);
5757
}
5858

59+
public function test_simple_dto_serialization_with_named_arguments(): void
60+
{
61+
$this->migrate(CreateMigrationsTable::class, new class implements DatabaseMigration {
62+
public string $name = '001_simple_character_named_args';
63+
64+
public function up(): QueryStatement
65+
{
66+
return new CreateTableStatement('characters')
67+
->primary()
68+
->text('name')
69+
->json('stats');
70+
}
71+
72+
public function down(): null
73+
{
74+
return null;
75+
}
76+
});
77+
78+
query(Character::class)
79+
->insert(
80+
name: 'Fern',
81+
stats: new CharacterStats(level: 25, health: 80, mana: 120),
82+
)
83+
->execute();
84+
85+
$retrievedCharacter = query(Character::class)
86+
->select()
87+
->first();
88+
89+
$this->assertSame('Fern', $retrievedCharacter->name);
90+
$this->assertInstanceOf(CharacterStats::class, $retrievedCharacter->stats);
91+
$this->assertSame(25, $retrievedCharacter->stats->level);
92+
$this->assertSame(80, $retrievedCharacter->stats->health);
93+
$this->assertSame(120, $retrievedCharacter->stats->mana);
94+
}
95+
5996
public function test_dto_with_enums(): void
6097
{
6198
$this->migrate(CreateMigrationsTable::class, new class implements DatabaseMigration {

0 commit comments

Comments
 (0)