=================================== Post-process JSON with headless.php =================================== This guide shows how to modify a Content Block's complete `data` array in PHP — the escape hatch when no declarative feature covers your case. When to use it (and when not) ============================= Reach for `headless.php` only for what the built-in features cannot do: +--------------------------------------+------------------------------------------------------------------------------------------------------------+ | Need | Use instead | +======================================+============================================================================================================+ | Responsive image variants | `Define image variants `__ (`headless.yaml`) | +--------------------------------------+------------------------------------------------------------------------------------------------------------+ | Menus, record lists, TypoScript data | `Add sub data processors `__ | +--------------------------------------+------------------------------------------------------------------------------------------------------------+ | Custom value/string shaping | `Custom normalizer `__ / `transformer `__ | +--------------------------------------+------------------------------------------------------------------------------------------------------------+ `headless.php` remains for genuinely block-specific logic — merging two fields, calling an API, reshaping the whole payload. **Maintenance note:** on the production site this extension was built for, 13 `headless.php` files existed whose only job was thumbnail generation. All of them are candidates for deletion since declarative image variants exist — see `Migrate legacy thumbnails `__ and the archived `legacy pattern <../_archive/LegacyHeadlessPhpThumbnails.rst>`__. Create the file =============== Place a `headless.php` next to the Content Block's `config.yaml`: .. code-block:: your_extension/ContentBlocks/ContentElements/your-block/headless.php The file receives the fully built `data` array and returns the modified one: .. code-block:: php $item) { $data['items'][$itemKey]['combinedTitle'] = trim($item['title'] . ' ' . $item['subtitle']); } // You can also add completely new keys... $data['lastModified'] = date(\DateTimeInterface::W3C); // ...or remove fields from the output unset($data['subtitle']); return $data; Rules: * The file is plain PHP included via `require` — keep it side-effect free apart from building the return value. * Return the array. A file that returns anything else (e.g. no `return` statement at all) throws an exception in a Development application context; in Production the processor falls back to the unmodified data. * The file runs on **every** render of this block type. Compatibility ============= The extension plans to pass a second parameter with the normalization `Context` (`function (array $data, Context $context)`) — not yet part of the stable API. Do not rely on it yet; see the `design record <../Design/ImproveToArray.rst>`__ (decision 4). Troubleshooting =============== Changes do not show up? `headless.php` is executed on every request — check that the file is really next to the block's `config.yaml` and that you are editing the Content Block the record actually uses (CType).