---
title: "Ansichten & Smarty"
description: "Wie `.tpl` Vorlagen aufgelöst werden, der `View::assign` Pipeline, das Caching und die gemeinsamen Partialen."
---

Ansichten in Nibiru sind **Smarty 3** Vorlagen. Jeder Controller hat eine Standardvorlage; eingebettete Aktionen können ihre eigenen haben. Das Singleton `View` umhüllt den Smarty-Engine und macht einen globalen Hilfsprogramm verfügbar: `View::assign()`.

## Wo sich die Templates befinden
```
application/view/
├── templates/                # source .tpl files (you write these)
│   ├── index.tpl             # → indexController::pageAction()
│   ├── products.tpl          # → productsController::pageAction()
│   ├── products/
│   │   └── detail.tpl        # → productsController::detailAction()
│   ├── shared/
│   │   ├── header.tpl
│   │   ├── footer.tpl
│   │   └── meta.tpl
│   ├── navigation.tpl
│   └── pageination.tpl       # (note the spelling)
├── templates_c/              # Smarty compile cache (auto)
├── cache/                    # rendered HTML cache (when caching=true)
└── mockup/                   # static design mockups
```
`templates_c/` wird von Smarty erstellt und verwaltet. **Sie muss vom Benutzer Ihrer Webserver-Instanz beschreibbar sein.** `cache/` wird nur verwendet, wenn `[ENGINE] caching = true`.

## Auflösungsregeln

Die Anzeigebene löst den Vorlagenpfad aus dem übereinstimmenden Controller heraus:

- Für `pageAction()` → `templates/<controller>.tpl`.
- Für eine benannte Aktion `fooAction()` → `templates/<controller>/foo.tpl`, falls sie existiert, andernfalls `templates/<controller>.tpl`.

Falls keines davon funktioniert, wird die [weiche 404](/core/dispatcher/#soft-404)-Fehlervorlage gerendert.

## Ein minimalistisches Template
```smarty
{include 'shared/header.tpl'}
<body>
{include file="navigation.tpl"}

<main class="container">
  <h1>{$title|escape}</h1>
  <ul>
    {foreach $products as $p}
      <li><a href="/products/detail/{$p.id}">{$p.name|escape}</a></li>
    {/foreach}
  </ul>
</main>

{include 'shared/footer.tpl'}
</body>
```
`{include 'shared/header.tpl'}` und `{include file="navigation.tpl"}` sind beide gültige Smarty-Include-Formen.

## View::assign

`View::assign()` ist die Art und Weise, wie PHP-Daten in Templates gelangen. Es ist statisch, idempotent und arbeitet gut mit Arrays zusammen:
```php
View::assign(['title' => 'Products']);
View::assign([
    'products' => $list,
    'count'    => count($list),
]);
```
Spätere Aufrufe überschreiben frühere für denselben Schlüssel. Innerhalb der Vorlagen werden diese zu `{$title}`, `{$products}`, `{$count}`.

Es gibt keine manuell aufzurufende `View::display()` – der Dispatcher ruft automatisch `Display::display()` auf, nachdem `pageAction()` zurückgegeben wurde.

## Freigegebene CSS/JS-Injektion

Die Konvention, die in den Showcase-Anwendungen verwendet wird, besteht darin, die konfigurierte Asset-Liste in die Vorlage zu übertragen:
```php
View::assign([
    'css' => Config::getInstance()->getConfig()[View::NIBIRU_SETTINGS]['smarty.css'],
    'js'  => Config::getInstance()->getConfig()[View::NIBIRU_SETTINGS]['smarty.js'],
]);
``````smarty
{* shared/header.tpl *}
<head>
  <meta charset="utf-8">
  <title>{$title|escape}</title>
  {foreach $css as $stylesheet}
    <link rel="stylesheet" href="{$stylesheet}">
  {/foreach}
</head>
```
Dann ist `[EINSTELLUNGEN] smarty.css[]` in der INI-Datei die einzige Quelle der Wahrheit für Stylesheets.

## Zwischenspeicherung

Das Cachen ist optional:
```ini
[ENGINE]
caching = true
```
Wenn aktiviert, speichert Smarty das gerenderte HTML im Verzeichnis `application/view/cache/` mit der Lebensdauer `Smarty::CACHING_LIFETIME_CURRENT` (Standard ≈ 1 Stunde). Löschen Sie den Cache mit:
```bash
./nibiru -cache-clear
```
Dies löscht sowohl `templates_c/` als auch `cache/` sicher.

::: caution
Gecachte Seiten führen Ihren Controller nicht aus. Verwenden Sie keine Caching für Seiten mit benutzerspezifischem Inhalt oder CSRF-Token.
:::

## Grundlagen von Smarty

Dinge, die Sie täglich benötigen:
```smarty
{* variables *}
{$user.name}
{$products[0].title}

{* iteration *}
{foreach $items as $item}
  ...
{foreachelse}
  No items.
{/foreach}

{* conditionals *}
{if $count > 0}…{else}…{/if}

{* string filters *}
{$body|escape}              {* HTML escape *}
{$date|date_format:"%Y-%m-%d"}
{$price|string_format:"%.2f"}

{* includes *}
{include file="shared/header.tpl" title=$title}

{* assigning *}
{assign var="now" value=time()}
```
## JSON-Antworten

Wenn eine Aktion `View::forwardToJsonHeader()` aufruft, wird Smarty umgangen und Nibiru gibt den zugewiesenen `data`-Schlüssel als JSON aus. Nützlich für AJAX-Endpunkte:
```php
public function searchAction() {
    View::forwardToJsonHeader();
    $results = $this->index->search($_REQUEST['q'] ?? '');
    View::assign(['data' => $results]);
}
```
## Navigationsumfang beinhaltet

`{include file="navigation.tpl"}` liest aus der im Abschnitt `[SETTINGS] navigation` konfigurierten JSON-Datei. Produktionsanwendungen laden oft **mehrere** benannte Navigationsarrays:
```php
public function navigationAction() {
    JsonNavigation::getInstance()->loadJsonNavigationArray('headnavigation');
    JsonNavigation::getInstance()->loadJsonNavigationArray('mainnavigation');
    JsonNavigation::getInstance()->loadJsonNavigationArray('footer');
}
```
Jeder benannte Array wird zu einer Smarty-Variablen mit dem gleichen Namen, bereit zur Darstellung im entsprechenden Partial.

## Häufige Probleme

- **`templates_c/` Berechtigungen** — wenn Smarty nicht darin schreiben kann, erhalten Sie einen schwerwiegenden Fehler. Führen Sie einmal `./nibiru -s` aus, um dies zu beheben.
- **`{$variable}` ohne Wert** — in der Standardmodus rendert Smarty nichts anstelle eines Throwns. Aktivieren Sie während der Entwicklung `error_reporting = E_ALL` und `[ENGINE] debug = true`, um Tippfehler zu erkennen.
- **HTML-Escape** — Smarty führt nicht automatisch das Escape durch. Verwenden Sie `|escape` für jede vom Benutzer gesteuerte Zeichenkette.
