Files
CodePress/guide/en/content-beheerder/content-api.md
T
E.Noorlander 06beef43d7 v2.6.3 (Lyra): Content multi-type handling, getAllPages() structuur, . verberg-prefix
- Content bestanden met dezelfde naam maar ander type (md/php/html) worden
  correct geserveerd: URL met extensie opent dat bestand, URL zonder extensie
  valt terug op md > php > html (resolveContentByType helper)
- Admin content editor accepteert bestanden met dezelfde naam (ander type);
  preview-knop linkt per extensie
- Frontend navigatie/directory listing/search tonen elk bestandstype apart
- getAllPages() array structuur gewijzigd naar list van
  ['path','title','type'] met type 'md'/'php'/'html'/'folder'
- Verberg-prefix logica: _ is geen verberg-prefix meer, alleen . (en -);
  admin toont wél alle . bestanden/mappen
- ContentAPI getPage()/pageExists() respecteren expliciete extensie
- Handleiding content-api.md (NL+EN) herschreven
- File-tree unificatie: _file-tree.twig + _editor-styles.twig includes
- Versie verhoogd naar 2.6.3
2026-08-20 16:45:53 +00:00

6.4 KiB

Content API

PHP content files (.php) run inside the CMS and have access to a safe, read-only API via the $api variable. The output of such a file is automatically placed into the active Twig layout at the {{ content }} spot.

How to pass content to the Twig template

There are two ways to send content from a .php file to the Twig template. The CMS picks the right one automatically:

  1. Echo / print — everything you echo (or that sits outside <?php ?> tags) is captured and placed as {{ content }} in the layout.
  2. Return — if you return a string, that string is used as {{ content }} (any echoed output is then ignored).

Example with echo:

---
layout: full_content
---
<?php
/** @var ContentAPI $api */
?>
<h1>Hello <?= htmlspecialchars($api->getSiteTitle()) ?></h1>
<p>Welcome to my page.</p>

Example with return:

---
layout: full_content
---
<?php
/** @var ContentAPI $api */
return '<h1>Hello ' . htmlspecialchars($api->getSiteTitle()) . '</h1>';

The frontmatter (--- block) is stripped by the CMS before the PHP code runs. The layout key determines which Twig template surrounds the content.

What you cannot do

  • You cannot set your own Twig variables from a .php file. PHP content only feeds the {{ content }} placeholder. Other template variables (menu, breadcrumb, page_title, etc.) are set by the CMS based on frontmatter and config — not by your PHP code.
  • You cannot call a ContentAPI from the outside; the class is only instantiated inside parsePHP() and is never reachable via a URL.

Available variables in your PHP file

The following variables are available inside a .php content file:

Variable Type Description
$api ContentAPI Read-only access to CMS data
$pageMetadata array The frontmatter metadata of this file

ContentAPI methods

Pages

  • getAllPages(): array — All content entries (folders + files) as a list of ['path' => ..., 'title' => ..., 'type' => ...]. type is md/php/html for files, folder for directories.
  • getPage(string $path): ?array — A specific page; returns title, content, path, layout, metadata. $path may include an extension.
  • pageExists(string $path): bool — Check whether a page exists
  • getCurrentPageTitle(): string — Title of the current page
  • getCurrentPagePath(): string — Path of the current page
  • isHomepage(): bool — Whether the current page is the homepage

Menu & navigation

  • getMenu(): array — Hierarchical menu structure with title, path, children, active
  • buildUrl(string $page = 'index', ?string $lang = null, array $params = []): string — Build a URL

Configuration

  • getConfig(string $key, mixed $default = null): mixed — Config value via dot notation (e.g. 'features.search_enabled')
  • getSiteTitle(): string — Site title from config

Language

  • getCurrentLanguage(): string — Current language code (e.g. 'nl')
  • getAvailableLanguages(): array — Available languages
  • t(string $key): string — Translate a language key
  • getSearchResults(): array — Search results (empty if not searching)
  • isSearching(): bool — Whether a search is currently active

Author

  • getPageAuthor(): array — Author metadata from frontmatter (author_name, author_email, created)

Examples

Show recent pages

---
layout: full_content
---
<?php
/** @var ContentAPI $api */
$entries = $api->getAllPages();
$currentLang = $api->getCurrentLanguage();
?>
<ul>
<?php foreach ($entries as $entry): ?>
    <?php if ($entry['type'] === 'folder') continue; // skip folders ?>
    <li>
        <a href="/<?= htmlspecialchars($currentLang) ?>/<?= htmlspecialchars($entry['path']) ?>">
            <?= htmlspecialchars($entry['title']) ?>
            <small>(<?= htmlspecialchars($entry['type']) ?>)</small>
        </a>
    </li>
<?php endforeach; ?>
</ul>

Use a config value

---
layout: full_content
---
<?php
/** @var ContentAPI $api */
if ($api->getConfig('features.search_enabled', false)): ?>
    <form method="GET" action="">
        <input type="search" name="search" placeholder="<?= $api->t('search_placeholder') ?>">
        <button type="submit"><?= $api->t('search_button') ?></button>
    </form>
<?php endif; ?>

Dynamic greeting based on language

---
layout: full_content
---
<?php
/** @var ContentAPI $api */
$lang = $api->getCurrentLanguage();
$greeting = $lang === 'nl' ? 'Welkom' : 'Welcome';
?>
<h1><?= $greeting ?> to <?= htmlspecialchars($api->getSiteTitle()) ?></h1>

Choosing a layout

The frontmatter layout key determines which Twig template surrounds your content. Available layouts are defined in themes/<active-theme>/theme.json under the template section. For example:

---
layout: sidebar-content
---

If you omit a layout, config.default_template is used, falling back to full_content. The content always lands at the {{ content }} spot in that template.

Security

  • Always use htmlspecialchars() for output of user-content or API data.
  • PHP content files have access to the server filesystem — be careful with include, require or file_get_contents on external paths. Stay inside the content/ directory.
  • The ContentAPI is read-only; you cannot modify files or config through it.

CMSAPI (for plugins)

Plugins use the CMSAPI class via $this->api. It offers similar methods:

$this->api->getCurrentPageTitle();
$this->api->getCurrentPageContent();
$this->api->getMenu();
$this->api->getConfig('site_title');
$this->api->getCurrentLanguage();
$this->api->isHomepage();
$this->api->hasContent();
$this->api->getSearchResults();
$this->api->isSearching();
$this->api->getAvailableLanguages();
$this->api->createUrl('about-us');
$this->api->translate('home');

In addition, CMSAPI has:

  • getCurrentPage(): array — Full page data
  • getCurrentPageUrl(): string — URL of the current page
  • getCurrentPageFileInfo(): ?array — File info (created, modified)
  • getBreadcrumb(): string — Breadcrumb HTML
  • executePhpFile(string $filePath): string — Execute a PHP file and capture output
  • getFileContent(string $filePath): string — Get content from a PHP/HTML/Markdown file
  • contentFileExists(string $filename): bool — Check whether a file exists in the content directory