---
title: "Contrôleurs"
description: "Écriture des contrôleurs Nibiru — le cycle d'action, View::assign et les modèles issus du code de production."
---

Un contrôleur Nibiru est une classe qui étend `Nibiru\Adapter\Controller`, se trouve dans `application/controller/<name>Controller.php`, et est chargé automatiquement par le [Dispatcher](/core/dispatcher/) lorsqu'une URL comme `/<name>/...` arrive.

## Anatomie d'un contrôleur
```php
<?php
namespace Nibiru;
use Nibiru\Adapter\Controller;

class productsController extends Controller
{
    public function pageAction() {
        View::assign([
            'title'    => 'Products',
            'products' => $this->loadProducts(),
        ]);
    }

    public function navigationAction() {
        JsonNavigation::getInstance()->loadJsonNavigationArray();
    }

    public function detailAction() {
        $id = (int) ($_REQUEST['id'] ?? 0);
        View::assign(['product' => $this->loadProduct($id)]);
    }

    private function loadProducts(): array { /* ... */ return []; }
    private function loadProduct(int $id): array { /* ... */ return []; }
}
```
## Le cycle de vie de l'action

Lorsque le dispatcheur appelle un contrôleur, il appelle les méthodes dans cet ordre fixe :

1. **`navigationAction()`** — remplir les menus globaux, fil d'Ariane, navigation basée sur le rôle.
2. **`<verbe>Action()`** — uniquement si `?_action=<verbe>` est défini ou si l'URL a un deuxième segment qui nomme une action.
3. **`pageAction()`** — dernier appel avant le rendu.

Les méthodes `navigationAction()` et `pageAction()` sont **toujours appelées**, même pour des actions inconnues. C'est pratique (vous n'avez jamais besoin de vérifier), mais cela peut vous surprendre si vous supposez que les actions sont exclusives.

## Communiquer avec la vue

`View::assign(['key' => $value, ...])` est la façon dont les données atteignent les modèles. C'est statique et peut être appelé autant de fois que vous le souhaitez — les appels ultérieurs écrabouillent ceux qui précèdent.
```php
View::assign(['title' => 'Products']);
View::assign(['products' => $list]);

// In templates/products.tpl:
//   {$title}     →  "Products"
//   {$products}  →  the array
```
Aides pratiques du contrôleur de base :
```php
$this->getRequest('id', false);   // $_REQUEST['id'] ?? false
$this->getPost('email', '');      // $_POST['email']  ?? ''
$this->getGet('page', 1);         // $_GET['page']    ?? 1
$this->getServer('REQUEST_URI');  // $_SERVER['REQUEST_URI']
$this->getFiles('upload');        // $_FILES['upload']
$this->getSession('auth');        // $_SESSION['auth']
```
Ces éléments existent en raison du fait que `Controller` est compatible avec `final` : vous pouvez les simuler dans les tests en remplaçant par une classe enfant.

## Redirection

Pour rediriger à l'intérieur d'une action :
```php
View::forwardTo('/login');             // 302 to the URL, exits
View::forwardToJsonHeader();           // sets Content-Type: application/json
```
`forwardToJsonHeader()` est le modèle canonique pour les points de terminaison JSON — définissez l'en-tête, attribuez `data`, puis retournez. La couche d'affichage s'occupe du reste.

## Plusieurs actions par contrôleur

Nibiru est heureux d'héberger un nombre quelconque d'actions par contrôleur. Le TPMS `erpController` de la production comporte `pageAction`, `navigationAction`, ainsi que `syncAction`, `statusAction`, `dryRunAction`, `cancelAction`, etc. — chaque action invoquée via `?_action=sync` ou `/erp/sync`.
```php
// /erp/sync  →  $_REQUEST['_action'] = 'sync'
public function syncAction(): void
{
    View::forwardToJsonHeader();
    if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
        View::assign(['data' => ['success' => false, 'error' => 'POST method required']]);
        return;
    }
    $result = AlphaplanSyncService::getInstance()->syncAbDocuments();
    View::assign(['data' => $result]);
}
```
## Travail avec les modules

Les contrôleurs sont minces. La plupart de la logique devrait résider dans les modules et leurs plug-ins :
```php
namespace Nibiru;
use Nibiru\Adapter\Controller;
use Nibiru\Module\Users\Plugin\User;

class loginController extends Controller
{
    private User $user;

    public function __construct() {
        parent::__construct();
        $this->user = new User();
    }

    public function authAction() {
        if (!$this->user->isAuthorized()) {
            View::assign(['loginForm' => $this->user->loginForm()]);
        } else {
            View::forwardTo('/index');
        }
    }
}
```
Ce modèle de *délégation* est cohérent dans les applications démonstratives : les contrôleurs coordonnent, tandis que les modules effectuent le travail.

## Contenu multilingue / Géré par un système de gestion de contenu (CMS)

Un modèle de `prod.maschinen-stockert.de` — chargez tout le texte sur la page à partir d'une table CMS cléée par le chemin du contrôleur :
```php
public function pageAction() {
    $controllerPath = $this->getController()
        . '/' . $this->getRequest('_action', 'page');

    $texts = Cms::init($this->getController())
        ->loadCmsTemplateTextsByControllerPath($controllerPath, $this->language);

    foreach ($texts as $t) {
        View::assign([
            $t['cms_template_texts_text_identifier'] =>
            $t['cms_template_texts_text_content']
        ]);
    }
}
```
Résultat : les non-développeurs peuvent modifier le contenu sans toucher au code. Le module CMS détient la table et l'interface d'édition ; le contrôleur charge simplement les chaînes de caractères.

## Génération des contrôleurs

Le CLI génère un contrôleur et son modèle en une seule étape :
```bash
./nibiru -c products
```
→ `application/controller/productsController.php`
→ `application/view/templates/products.tpl`

Les deux sont peuplés avec le squelette canonique. Vous êtes prêt à écrire.
