---
title: "Vues & Smarty"
description: "Comment les modèles .tpl sont résolus, le pipeline View::assign, le cache et les parties partagées."
---

Les vues dans Nibiru sont des modèles **Smarty 3**. Chaque contrôleur a un modèle par défaut ; les actions imbriquées peuvent en avoir leurs propres. Le singleton `View` encapsule le moteur Smarty et expose un seul assistant global : `View::assign()`.

## Où se trouvent les modèles
```
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/` est créé et géré par Smarty. **Il doit être accessible en écriture pour l'utilisateur de votre serveur web.** `cache/` n'est utilisé que lorsque `[ENGINE] caching = true`.

## Règles de résolution

La couche d'affichage résout le chemin du modèle à partir du contrôleur correspondant :

- Pour `pageAction()` → `templates/<controller>.tpl`.
- Pour une action nommée `fooAction()` → `templates/<controller>/foo.tpl` si elle existe, sinon `templates/<controller>.tpl`.

Si aucune des deux solutions ne fonctionne, le modèle d'erreur [soft 404](/core/dispatcher/#soft-404) est rendu.

## Un modèle minimal
```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'}` et `{include file="navigation.tpl"}` sont toutes deux des formes d'inclusion Smarty valides.

## View::assign

`View::assign()` est la façon dont les données PHP atteignent les modèles. C'est statique, idempotent et convivial avec les tableaux :
```php
View::assign(['title' => 'Products']);
View::assign([
    'products' => $list,
    'count'    => count($list),
]);
```
Les appels ultérieurs écrasent ceux qui précèdent pour la même clé. À l'intérieur des modèles, ils deviennent `{$title}`, `{$products}`, `{$count}`.

Il n'y a pas de `View::display()` que vous appelez manuellement — le dispatcheur invoque automatiquement `Display::display()` après que `pageAction()` a retourné.

## Injection partagée CSS/JS

La convention utilisée dans les applications démonstratives consiste à pousser la liste des actifs configurés dans le modèle :
```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>
```
Alors `[SETTINGS] smarty.css[]` dans le fichier INI est la seule source de vérité pour les feuilles de style.

## Mise en cache

Le mise en cache est facultative :
```ini
[ENGINE]
caching = true
```
Lorsqu'il est activé, Smarty met en cache le HTML rendu dans `application/view/cache/` avec une durée de vie `Smarty::CACHING_LIFETIME_CURRENT` (par défaut environ 1 heure). Effacez le cache avec :
```bash
./nibiru -cache-clear
```
Cela supprime en toute sécurité à la fois `templates_c/` et `cache/`.

:::caution
Les pages mises en cache ne lancent pas votre contrôleur. Ne mettez pas en cache les pages contenant du contenu spécifique à l'utilisateur ou des jetons CSRF.
:::

## Essentiels de Smarty

Les choses que vous utiliserez quotidiennement :
```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()}
```
## Réponses JSON

Lorsqu'une action appelle `View::forwardToJsonHeader()`, Smarty est contourné et Nibiru émet la clé `data` assignée sous forme de JSON. Utile pour les points d'accès AJAX :
```php
public function searchAction() {
    View::forwardToJsonHeader();
    $results = $this->index->search($_REQUEST['q'] ?? '');
    View::assign(['data' => $results]);
}
```
## La navigation comprend

`{include file="navigation.tpl"}` lit le fichier JSON configuré dans `[SETTINGS] navigation`. Les applications de production chargent souvent plusieurs tableaux de navigation nommés :
```php
public function navigationAction() {
    JsonNavigation::getInstance()->loadJsonNavigationArray('headnavigation');
    JsonNavigation::getInstance()->loadJsonNavigationArray('mainnavigation');
    JsonNavigation::getInstance()->loadJsonNavigationArray('footer');
}
```
Chaque tableau nommé devient une variable Smarty du même nom, prêt à être rendu dans le partial correspondant.

## Problèmes courants

- **Permissions du dossier `templates_c/`** — si Smarty ne peut pas y écrire, vous obtiendrez une erreur fatale. Exécutez une fois `./nibiru -s` pour corriger le problème.
- **Variable `{$variable}` sans valeur** — par défaut, Smarty ne rend rien plutôt que de lever une exception. Activez `error_reporting = E_ALL` et `[ENGINE] debug = true` pendant le développement pour repérer les fautes d'orthographe.
- **Échappement HTML** — Smarty n'échappe pas automatiquement. Utilisez `|escape` pour toute chaîne contrôlée par l'utilisateur.
