Description
Symfony version(s) affected
7.3
Description
Hi there,
I'm using Symfony as an Backend-API and have changed the last weeks to use the ObjectMapper.
At updating existing entitys is a problem it doesn't work always. To create an new entity it always works fine. At first I thought it cause of nested entitys, but it's also an "top level" entity. I have two examples for that.
How to reproduce
First example (nested entity)
#Controller.php
#[Route('/klasse-turnier-zuord/{klasse_turnier_zuord_id}/edit', name: "turnier-work-klasse-turnier-klasse-zuord-edit", methods: ["PATCH"], format: "json")]
public function klasseEdit(
#[MapRequestPayload] KlasseMitTurnierZuordDTO $klasseMitTurnierZuordDTO,
int $klasse_turnier_zuord_id, ): JsonResponse
{
$klasseTurnierZuordAktuell = $this->klasseTurnierZuordRepos->findOneBy([
'turnier' => $this->turnier,
'id' => $klasse_turnier_zuord_id]);
if ($klasseTurnierZuordAktuell instanceof KlasseTurnierZuord)
{
$klAkt = $klasseTurnierZuordAktuell->getKlasse();
$klDTO = $klasseMitTurnierZuordDTO->klasse;
// just shorten for the comparison bellow
$genAkt = [];
foreach ($klAkt->getGender() as $gen)
{
$genAkt[] = $gen->getId();
}
if (($klAkt->getStandard())
&& (($klAkt->getName() != $klDTO->name)
|| ($klAkt->getBogentyp()->getId() != $klDTO->bogentyp_id)
|| ($klAkt->getAltersklasseVon()->getId() != $klDTO->altersklasse_von_id)
|| ($klAkt->getAltersklasseBis()->getId() != $klDTO->altersklasse_bis_id)
|| ($klAkt->getApollonKlasseNr() != $klDTO->apollon_klasse_nr)
|| ($genAkt != $klDTO->gender_id)))
{
$this->objectMapper->map($klasseMitTurnierZuordDTO->klasse, $klasseTurnierZuordAktuell->getKlasse());
$klasseTurnierZuordAktuell->getKlasse()->unsetId();
$klasseTurnierZuordAktuell->getKlasse()->setStandard(false);
}
else
{
$this->objectMapper->map($klasseMitTurnierZuordDTO->klasse, $klasseTurnierZuordAktuell->getKlasse());
}
}
return $this->json([]);
}
#KlasseMitTurnierZuordDTO.php
class KlasseMitTurnierZuordDTO
{
public function __construct(
public readonly KlasseDTO $klasse,
public readonly KlasseTurnierZuordDTO $klasse_turnier_zuord,
)
{
}
}
#KlasseDTO.php
#[Map(target: Klasse::class)]
class KlasseDTO
{
public function __construct(
public readonly bool $standard,
#[Map(target: "inter_nat", transform: KlasseInterNatTransformer::class)]
public readonly array $inter_nat,
public readonly ?int $gueltig_von,
public readonly ?int $gueltig_bis,
public readonly string $name,
#[Map(target: 'bogentyp', transform: BogentypTransformer::class)]
public readonly ?int $bogentyp_id,
#[Map(target: 'altersklasse_von', transform: AltersklasseVonTransformer::class)]
public readonly ?int $altersklasse_von_id,
#[Map(target: 'altersklasse_bis', transform: AltersklasseBisTransformer::class)]
public readonly ?int $altersklasse_bis_id,
public readonly ?int $apollon_klasse_nr,
#[Map(target: 'gender', transform: GenderTransformer::class)]
public readonly array $gender_id,
#[Map(target: 'klasse_turniertyp_zuord', transform: KlasseTurniertypZuordTransformer::class)]
public readonly ?array $turniertyp_zuord = null, )
{
}
}
On dumping the DTO-object there's the new value, but it isn't mapped to the entity.
I also have tested to don't get the Klasse entity from the $klasseTurnierZuordAktuell, load it with the entity manager by id, but some result.
second example ("top level" entity)
#Controller
#[Route('/einstellungen', name: "turnier-work-meldung-einstellungen", methods: ["PATCH"], format: "json")]
public function einstellungen(
#[MapRequestPayload] TurnierMeldungEinstellungenDTO $turnierMeldungEinstellungenDTO): JsonResponse
{
try
{
$this->objectMapper->map($turnierMeldungEinstellungenDTO, $this->turnier);
$this->eM->persist($this->turnier);
$this->eM->flush();
$this->eM->refresh($this->turnier);
$this->subscriber->setResponseSuccess(true);
return $this->json($this->turnier->getArrayOwner());
}
catch (Exception $e)
{
dump($e);
$this->subscriber->setResponseError([1, 43, 1, 1]);
}
return $this->json([]);
}
#TurnierMeldungEinstellungenDTO.php
#[Map(target: Turnier::class)]
class TurnierMeldungEinstellungenDTO
{
public function __construct(
#[Map(target: 'meldeschluss_date', transform: DateTimeTransformer::class)]
public readonly string $meldeschluss_date,
public readonly string $meldung_neu_nach_meldeschluss,
public readonly bool $meldung_edit_nach_meldeschluss,
public readonly bool $meldung_delete_nach_meldeschluss,
public readonly bool $delete_meldung_autoremove_startliste,
public readonly bool $mehrfach_meldung_moeglich,
public readonly bool $meldung_ohne_eindeutig_klassenzuordnung,
public readonly bool $meldung_klassenzuordnung_melder_manuell,
public readonly bool $melden_mannschaft,
public readonly bool $meldung_ohne_quali,
public readonly bool $meldung_ohne_datenpruefung,
public readonly bool $meldung_ohne_startberechtigung,
public readonly bool $meldung_check_hoeherstufung,
)
{
}
}
The TurnierMeldungEinstellungenDTO isn't an DTO of the full target, there are only properties how would be changed some settings.
Possible Solution
No response
Additional Context
I have shorten the controller codes for easier to read and understand here. I also have tested the shorten codes, but there's the some problem, so it's not caused on the code around the mapper.
If I exchange the existing entities with empty entities the mapping works well.