Computed Fields Without a Database Column
Computed Fields Without a Database Column
~13 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026
NOT every field in the API response has to come from a database column – a GETTER with no corresponding #[ORM\Column] is already enough.
isRecent as a computed field
#[Groups(['project:read'])]
public function isRecent(): bool
{
$sevenDaysAgo = new \DateTimeImmutable('-7 days');
return $this->createdAt > $sevenDaysAgo;
}NO #[ORM\Column], NO property – JUST a public method named isX() with #[Groups] in front of it. API Platform (more precisely: the underlying Symfony Serializer) AUTOMATICALLY recognizes is*() AND get*() methods as serializable properties.
Checking the result
curl -k https://localhost/api/projects/1{
"id": 1,
"name": "Website Relaunch",
"description": "Complete redesign",
"createdAt": "2026-08-06T12:00:00+00:00",
"isRecent": true
}isRecent appears in the JSON EVEN THOUGH the database table has NO corresponding column – the value gets recomputed on EVERY request, so it's ALWAYS current, unlike a stored, potentially STALE value.
When computed fields make sense
- Values derived from fields that ALREADY exist (like
isRecentfromcreatedAt). - Aggregations across relationships, e.g. a task count (relevant FROM block 5, once
Projectis linked toTask). - Formatted representations for the frontend, e.g. a ready-composed display name.
Achtung: Computed fields are ONLY readable (normalizationContext), NEVER also in denormalizationContext – there is NO setter counterpart, a write attempt would simply go NOWHERE.
Tipp: Performance note: computed fields that access RELATIONSHIPS (chapter 41+) can lead to N+1 database queries if the relationship isn't eager-loaded – this topic is covered in depth in block 5, once real relations exist.