Die Mächtigkeit von virtuellen Feldern in Payload CMS
Virtuelle Felder in Payload CMS sind dynamisch berechnete, schreibgeschützte Felder, die ihren Wert zur Laufzeit ableiten. Dieser Artikel zeigt Einsatzszenarien wie vollständige Namen und geschätzte Lesezeit – ohne redundante Datenhaltung.
Geschrieben von
Veröffentlicht am
17. Dezember 2024
Zuletzt aktualisiert am
1. Juli 2026
Tags
Beim Arbeiten mit Payload CMS gibt es Fälle, in denen API-Werte nicht manuell eingegeben oder persistent in der Datenbank gespeichert werden sollen. Stattdessen werden diese Werte spontan berechnet oder aus anderen Daten abgeleitet. Hier kommen virtuelle Felder ins Spiel.
Dieser Artikel behandelt, was virtuelle Felder sind, wie und wann man sie einsetzt, und gibt praktische Beispiele.
Was sind virtuelle Felder?
Virtuelle Felder in Payload CMS sind dynamisch berechnete Felder, die nicht in der Datenbank gespeichert werden. Stattdessen werden sie während des Leseprozesses des Dokuments über einen afterRead-Hook befüllt. Dieser Hook wird ausgeführt, nachdem das Dokument aus der Datenbank gelesen wurde, aber bevor es an den Aufrufer zurückgegeben wird.
Da virtuelle Felder nicht in der Datenbank existieren, sind sie schreibgeschützt, nicht abfragbar, können nicht für das Sortieren verwendet werden und sind nicht dafür geeignet, als useAsTitle verwendet zu werden.
Wie macht man ein Feld in Payload CMS virtuell?
Seit Payload v3.0.0 lässt sich ein virtuelles Feld definieren, indem man die virtual: true Eigenschaft zur Feldkonfiguration hinzufügt. Dies teilt Payload mit, dass das Feld nicht in der Datenbank gespeichert werden soll. Der Wert kann dann dynamisch befüllt werden, typischerweise mit einem afterRead Hook.
Wie man den Wert virtueller Felder festlegt
Es gibt zwei gängige Wege, virtuelle Felder in Payload CMS zu befüllen, abhängig vom Anwendungsfall:
Über einen Feld-Hook
Der gebräuchlichste und einfachste Ansatz – ideal für einzelne virtuelle Felder. Die Logik bleibt im afterRead-Hook innerhalb der Felddefinition gekapselt.
import { CollectionConfig } from 'payload'
export const Users: CollectionConfig = {
slug: 'users',
fields: [
{ name: 'firstName', type: 'text' },
{ name: 'lastName', type: 'text' },
{
name: 'fullName',
type: 'text',
virtual: true,
admin: { readOnly: true },
hooks: {
afterRead: [
({ siblingData }) =>
[siblingData.firstName, siblingData.lastName].filter(Boolean).join(' '),
],
},
},
],
} Über einen Collection-Hook
Diese Methode eignet sich, wenn mehrere virtuelle Felder festgelegt werden müssen, die von gemeinsamer Logik oder verwandten Daten abhängen. Beispielsweise wenn ein Slug- und ein Parent-Feld im Dokument gespeichert sind und ein virtuelles Path- und ein AlternatePaths-Feld abgeleitet werden sollen, ist es sinnvoll, einen beforeRead- oder afterRead-Collection-Hook zu verwenden und sie gemeinsam zu berechnen.
⚠️ Hinweis: Bei Hooks auf Sammlungsebene wie afterRead empfiehlt es sich, zunächst zu prüfen, ob ein bestimmtes virtuelles Feld angefordert wurde. So werden unnötige Berechnungen vermieden, wenn das Feld nicht benötigt wird.
Anwendungsfälle
Virtuelle Felder sind besonders nützlich, um Dokumente mit dynamisch berechneten oder abgeleiteten Werten anzureichern, ohne sie in der Datenbank zu speichern. Typische Anwendungsfälle:
Kombinieren von Daten aus nicht-virtuellen Feldern
Der einfachste und häufigste Anwendungsfall ist die Kombination vorhandener Felder innerhalb desselben Dokuments.
Beispiel: Kombinieren von Vor- und Nachname
Hier ist ein einfaches Beispiel, das einen vollständigen Namen auf der Grundlage von zwei vorhandenen Feldern erzeugt: Vorname und Nachname.
import { CollectionConfig } from 'payload'
export const Users: CollectionConfig = {
slug: 'users',
fields: [
{ name: 'firstName', type: 'text' },
{ name: 'lastName', type: 'text' },
{
name: 'fullName',
type: 'text',
virtual: true,
admin: { readOnly: true },
hooks: {
afterRead: [
({ siblingData }) =>
[siblingData.firstName, siblingData.lastName].filter(Boolean).join(' '),
],
},
},
],
} Dies ist in vielen realen Szenarien nützlich, z. B. in Benutzerprofilen, Autorenanzeigen oder Kontaktlisten, wo es von Vorteil ist, den vollständigen Namen vorberechnet zu haben.
Berechnungen auf der Grundlage bestehender Felder
Ein weiteres häufiges Muster ist die Durchführung einfacher Berechnungen anhand von Feldwerten aus den Daten eines Geschwisterfelds.
Beispiel: Geschätzte Lesedauer für Blogbeiträge
Beispiel: Ein Blog soll die Lesezeit pro Beitrag anzeigen. Anstatt diesen Wert manuell einzugeben, lässt er sich mit einem virtuellen Feld aus dem Inhalt des Beitrags berechnen.
import { CollectionConfig } from 'payload'
import { convertLexicalToPlaintext } from '@payloadcms/richtext-lexical'
export const BlogPosts: CollectionConfig = {
slug: 'blog-posts',
fields: [
{ name: 'content', type: 'richText' },
{
name: 'readingTime',
type: 'number',
virtual: true,
admin: { readOnly: true },
hooks: {
afterRead: [
({ siblingData }) => {
const plaintext = convertLexicalToPlaintext({ data: siblingData.content })
const wordCount = plaintext.split(/\s+/).length
return Math.ceil(wordCount / 200)
},
],
},
},
],
} In diesem Beispiel ist convertLexicalToPlaintext ist eine von Payload angebotene Utility-Funktion, die Rich-Text- oder Lexical-Editor-Inhalte zur Analyse in einfachen Text umwandelt.Zusammenführen oder Einspeisen von internen oder externen Daten (asynchrone virtuelle Felder)
Zu den fortgeschritteneren Anwendungsfällen gehört die asynchrone Anreicherung von Dokumenten mit Daten aus anderen Sammlungen oder externen APIs.
import { CollectionConfig } from 'payload'
export const Locations: CollectionConfig = {
slug: 'locations',
fields: [
{ name: 'city', type: 'text' },
{
name: 'weather',
type: 'text',
virtual: true,
admin: { readOnly: true },
hooks: {
afterRead: [
async ({ siblingData }) => {
const res = await fetch(`https://wttr.in/${siblingData.city}?format=3`)
return res.text()
},
],
},
},
],
} Ideal für Anwendungsfälle wie das Abrufen der neuesten Wechselkurse, die Anzeige von Echtzeit-Wetterbedingungen auf der Grundlage eines Standortfelds oder die Anzeige verwandter Daten aus einer anderen Sammlung.
Gut zu wissen bei der Verwendung virtueller Felder
-
virtual: trueallein macht ein Feld nicht schreibgeschützt;admin.readOnly: trueverhindert, dass Benutzer ungespeicherte Werte in das Verwaltungsfenster eingeben. - Virtuelle Felder, die sich ausschließlich auf einen
afterRead-Hook verlassen, um Daten auf der Grundlage eines anderen Feldes aufzufüllen, zeigen keinen Wert an, wenn ein neues Dokument erstellt wird, und werden im Verwaltungsbereich nicht live aktualisiert, wenn sich das Quellfeld ändert. Verwenden Sie eine benutzerdefinierte Komponente, um das Echtzeitverhalten zu aktivieren. - Wenn sie als
requiredmarkiert sind, können virtuelle Felder fehlschlagen, wenn derafterRead-Hook noch nicht ausgeführt wurde, deaktivieren Sie die Validierung mitvalidate: () => true.
Warum virtuelle Felder verwenden?
Virtuelle Felder bieten eine elegante Möglichkeit, Dokumente mit dynamisch generierten Feldern anzureichern. Ideal ist der Einsatz, wenn statische Daten von dynamisch abgeleiteten Werten getrennt werden sollen, damit die Datenbank schlank bleibt und sich auf rohe, manuell verwaltete Inhalte konzentriert.
Wichtige Vorteile:
- Immer aktuell: Virtuelle Felder werden on-the-fly generiert und spiegeln stets den aktuellen Zustand des Quellfelds wider.
- Ideal für Präsentationswerte: Virtuelle Felder eignen sich für Werte, die ausschließlich der Darstellung dienen, wie Labels oder Zusammenfassungen.
- Klare Trennung der Zuständigkeiten: Statische und berechnete Inhalte bleiben sauber getrennt.
- Perfekt für read-only abgeleitete Daten: Nützlich für Werte wie vollständige Namen, Lesezeiten oder berechnete Slugs, die keine Benutzereingabe erfordern.
Wann man keine virtuellen Felder verwenden sollte
So hilfreich virtuelle Felder auch sind – es gibt Fälle, in denen sie ungeeignet sind:
- Notwendigkeit zum filtern oder sortieren: Virtuelle Felder werden nicht gespeichert und können daher nicht in Abfragen verwendet werden.
- Der Wert soll dauerhaft bestehen bleiben: Wenn sich ein Wert historisch nicht verändern darf (z. B. Lesezeit zum Veröffentlichungszeitpunkt), ist ein virtuelles Feld ungeeignet.
- Komplexe oder asynchrone Berechnungen: Aufwändige Berechnungen oder externe API-Aufrufe können die Ladezeit bei großen Datenmengen deutlich verlangsamen.
Alternativen zu virtuellen Feldern
- Gespeicherte abgeleitete Felder mit Sync-Logik: Berechnete Werte (wie Lesezeit) können in der Datenbank gespeichert und über Hooks (
beforeChange,afterChange) aktualisiert werden, wenn sich Quellfelder ändern. Dies ermöglicht Abfragen und Sortierung, erfordert aber Synchronisierungslogik. - Admin-editierbare Felder: Wenn ein Feld manuell angepasst oder gelegentlich überschrieben werden muss, ist ein reguläres gespeichertes Feld mit optionalem Standardwert besser geeignet.
Relationship Virtual Fields
Mit Payload v3.35.0 wurde eine neue Funktion eingeführt: Virtuelle Felder können nun direkt mit einem bestimmten Feld eines verknüpften Dokuments verbunden werden.
Was sind Relationship Virtual Fields?
Ein Relationship Virtual Field erlaubt es, ein Feld aus einem verknüpften Dokument (z. B. über ein relationship- oder upload-Feld) auszulesen und es im aktuellen Dokument bereitzustellen – ohne es zu speichern.
Besonders: Dieses Feld wird immer mit dem verknüpften Wert gefüllt – auch bei depth: 0. Im Gegensatz zu regulären virtuellen Feldern können Relationship Virtual Fields sogar gefiltert und sortiert werden.
Virtuelle Felder „extrahieren sich“ gewissermaßen gezielt ein bestimmtes Feld aus einem verknüpften Dokument – sogar tief verschachtelte Felder wie person.location.city.
Im folgenden Beispiel referenziert jedes Dokument in der Collection authors einen Eintrag aus der Collection persons über das Feld person. Das virtuelle Feld name übernimmt automatisch den Wert von person.title:
import { CollectionConfig } from 'payload'
export const Authors: CollectionConfig = {
slug: 'authors',
fields: [
{
name: 'person',
type: 'relationship',
relationTo: 'persons',
},
{
name: 'name',
type: 'text',
virtual: 'person.title',
},
],
} Wann Relationship Virtual Fields sinnvoll sind
Relationship Virtual Fields eignen sich, wenn:
- ein bestimmtes Feld aus einem verknüpften Dokument (z. B.
category.title) angezeigt werden soll, ohne die Daten zu duplizieren. - Dokumente basierend auf einem Feld aus einem verknüpften Dokument gefiltert oder sortiert werden sollen.
- ein Feld aus einem verknüpften Dokument als Titel des aktuellen Dokuments über
useAsTitleverwendet werden soll.
⚠️ Hinweis: Das genutzte Relationship-Feld muss eine einfache, nicht-polymorphe Beziehung sein. Felder mit hasMany: true oder polymorphe Beziehungen werden nicht unterstützt.Fazit
Virtuelle Felder sind ein mächtiges Feature in Payload CMS, mit dem Dokumente dynamisch angereichert werden können – ganz ohne redundante Datenhaltung oder aufgebähte Schemata. Egal, ob vollständige Namen, Lesezeiten oder komplexe API-Responses: Virtuelle Felder halten die Datenbank schlank und die API ausdrucksstark.