---
title: "Bootstrap & Dispatcheur"
description: "Comment une requête Nibiru traverse `index.php` jusqu'à votre contrôleur via le dispatcheur."
---

Une requête Nibiru effectue un parcours dans trois fichiers : `index.php`, `core/framework.php` et `core/c/dispatcher.php`. En les lisant dans cet ordre, vous obtenez toutes les informations nécessaires.

## index.php
```php
<?php
require_once 'core/framework.php';
```
C'est le fichier complet. `index.php` existe uniquement pour donner une cible au serveur web.

## core/framework.php

`framework.php` nécessite les classes du framework dans l'ordre des dépendances — paramètres, registre, routeur, moteur, chargeur automatique, tous les pilotes de base de données, toutes les 28 types de formulaires, vue, contrôleur, modules, authentification, débogage, affichage — et se termine par :
```php
Nibiru\Dispatcher::getInstance()->run();
```
Ce seul appel est le battement cardiaque de votre application.

## Dispatcher::run()

Le flux simplifié :
```php
public function run() {
    date_default_timezone_set(Config::getInstance()->getConfig()
        [View::NIBIRU_SETTINGS]['timezone']);

    if (Config::getInstance()->getConfig()
        [self::CONFIG_GENERATOR_SECTION][self::GENERATOR_DATABASE]) {
        new Model(false);                          // 1. (re)generate models from schema
    }

    Router::getInstance()->route();                // 2. parse the URL
    Auto::loader()->loadModelFiles();              // 3. load model files
    Auto::loader()->loadModules();                 // 4. load module classes

    $tpl = Router::getInstance()->tplName();
    $controllerFile = __DIR__ . "/../../application/controller/{$tpl}Controller.php";

    if (is_file($controllerFile)) {                // 5. controller file exists
        require_once $controllerFile;
        $class = "Nibiru\\{$tpl}Controller";
        $controller = new $class();

        if (array_key_exists('_action', $_REQUEST)) {
            $action = $_REQUEST['_action'] . 'Action';
            $controller->navigationAction();
            if (method_exists($controller, $action)) {
                $controller->$action();            // 6. optional named action
            }
            $controller->pageAction();
        } else {
            $controller->navigationAction();
            $controller->pageAction();
        }

        Display::getInstance()->display();         // 7. render Smarty
    } else {
        // 8. soft 404 — render the configured error controller
    }
}
```
## La séquence d'action

Chaque requête passe par les mêmes trois étapes si `?_action=foo` est défini :

1. `navigationAction()` — remplir les menus, fil d'Ariane.
2. `fooAction()` — exécuter l'action nommée.
3. `pageAction()` — dernière occasion d'assigner des données de modèle.

Sans `_action`, seules les étapes 1 et 3 s'exécutent.

Cela signifie que la logique d'exécution sans état doit être placée dans `pageAction()`, et les données de navigation doivent être placées dans `navigationAction()`, même si cela ressemble à dupliquer l'effort. Deux contrôleurs dans le même projet auront tous deux une méthode `navigationAction()` ; c'est correct.

## Soft 404

Si le fichier de contrôleur correspondant n'existe pas, Nibiru affiche un *404 doux* — il retourne un 200 OK et rend le contrôleur nommé dans `[ENGINE] error.controller` (par défaut : `error`). C'est intentionnel : cela vous permet de servir des pages d'erreur agréables sans configuration au niveau du serveur.

Si vous souhaitez un véritable code HTTP `404 Not Found`, définissez-le dans votre contrôleur d'erreurs :
```php
public function pageAction() {
    http_response_code(404);
    View::assign(['title' => 'Lost in the void']);
}
```
## Auto::loader()

Deux chargeurs automatiques s'exécutent avant la construction du contrôleur :

- **`loadModelFiles()`** parcourt `application/model/` et inclut chaque fichier `.php` trouvé. Les modèles générés sont des fichiers simples, sans paquets nommés, donc c'est une simple boucle `require_once`.
- **`loadModules()`** explore `application/module/<name>/` et charge la classe principale de chaque module ainsi que ses fichiers trait, plugin et interface. Le Registre indexe en même temps les paramètres INI de chaque module.

Les deux utilisent les chemins configurés dans `[SETTINGS] modules.path` etc., donc vous pouvez les remplacer par environnement.

## Gestion des URLs pour le référencement

Avant la résolution du contrôleur, `Router::route()` exécute `handleSeoUrls()`, qui détecte les URL sous la forme `/controller/<slug>/<id>` (où le deuxième segment *n'est pas* une action connue et le troisième est numérique). Ces URL sont réécrites internalement en `/controller/detail/` avec `$_REQUEST['id']` et `$_REQUEST['slug']` remplis. Pour plus d'informations, consultez [Routing](/core/routing/).

## Quand remplacer le dispatcheur

Presque jamais. Les points d'extension les plus propres sont :

- **Contrôleur d'erreur personnalisé** — définissez `[ENGINE] error.controller`.
- **Accroches pré-controller** — chargez un module qui enregistre un observateur, puis attachez-le à l'intérieur de `navigationAction()`.
- **Entrée style cron** — exécutez le framework sans tête via la CLI `nibiru` plutôt que `index.php`.
