---
title: "Modèles"
description: "Comment Nibiru génère automatiquement les classes de modèle à partir de votre schéma de base de données et comment les étendre."
---

La couche modèle de Nibiru est *schéma-premier*. Vous ne rédigez pas les modèles à la main — le framework lit votre base de données et génère une classe PHP par table à chaque démarrage.

## Comment la génération fonctionne

Lorsque `[GENERATOR] database = true` dans votre fichier INI, le dispatcheur exécute `new Model(false)` à chaque requête, ce qui :

1. Se connecte au pilote actif.
2. Liste les tables dans la base de données configurée (`information_schema.tables` pour PG, `SHOW TABLES` pour MySQL).
3. Pour chaque table, écrit `application/model/<table>.php` contenant une classe qui étend l'adaptateur `Db` approprié et intègre une constante `TABLE` décrivant les colonnes.

Le réexécution est peu coûteuse : le générateur écrase uniquement lorsque le schéma a changé, donc les modèles enregistrés conservent leurs méthodes manuscrites *si* vous définissez `database = false` après la première exécution.
```ini
[GENERATOR]
database          = true     ; regenerate models on each request
database.overwrite = true    ; if false, generator won't touch existing files
```
En production, définissez `database = false` afin que les modèles ne soient pas régénérés à chaque requête.

## Un modèle généré

Pour une table `users` avec les colonnes `user_id, user_login, user_pass, user_email`:
```php
<?php
namespace Nibiru\Model;
use Nibiru\Adapter\MySQL\Db;

class users extends Db
{
    const TABLE = [
        'table' => 'users',
        'field' => [
            'user_id'    => 'user_id',
            'user_login' => 'user_login',
            'user_pass'  => 'user_pass',
            'user_email' => 'user_email',
        ],
    ];

    public function __construct() {
        self::initTable(self::TABLE);
    }
}
```
L'adaptateur `Db` vous offre des assistants simples CRUD via `Pdo::` (ou le pilote actif) :
```php
$users = new \Nibiru\Model\users();

// Read by primary key
$row = \Nibiru\Pdo::fetchRowInArrayById('users', ['user_id' => 42]);

// Read all
$all = \Nibiru\Pdo::fetchAll('SELECT * FROM users WHERE user_account_active = 1');

// Insert
\Nibiru\Pdo::insert('users', [
    'user_login' => 'marduk',
    'user_email' => 'marduk@nibiru.local',
]);

// Update
\Nibiru\Pdo::update('users',
    ['user_email' => 'new@nibiru.local'],
    ['user_id' => 42]);

// Delete
\Nibiru\Pdo::delete('users', ['user_id' => 42]);
```
## Requêtes personnalisées

La classe générée est une classe PHP simple — ajoutez des méthodes librement :
```php
namespace Nibiru\Model;
use Nibiru\Adapter\MySQL\Db;
use Nibiru\Pdo;

class documentation extends Db
{
    const TABLE = [
        'table' => 'documentation',
        'field' => [
            'id' => 'id', 'title' => 'title', 'slug' => 'slug',
            'content' => 'content', 'category' => 'category',
            'version' => 'version',
        ],
    ];

    public function __construct() { self::initTable(self::TABLE); }

    public function getBySlug(string $slug): ?array {
        return Pdo::fetchRowInArrayById(
            self::TABLE['table'],
            [self::TABLE['field']['slug'] => $slug]
        ) ?: null;
    }

    public function search(string $query): array {
        $sql = 'SELECT * FROM ' . self::TABLE['table']
             . ' WHERE title LIKE :q OR content LIKE :q ORDER BY title';
        return Pdo::fetchAll($sql, [':q' => '%' . $query . '%']);
    }
}
```
Si le générateur s'exécute à nouveau avec `database.overwrite = true`, il remplacera ce fichier. Gardez les méthodes personnalisées dans une classe enfant ou définissez `database.overwrite = false` après la première génération.

## Modèle mince + module de plug-in

Pour les domaines complexes (authentification, facturation, analyse), les applications de démonstration mettent les méthodes de requête sur un **plugin de module** plutôt que sur le modèle brut. Le plugin détient les règles métier ; le modèle est simplement une référence typée à la table :
```
application/module/users/
├── plugins/
│   └── user.php         # User::isAuthorized(), User::loginForm(), …
└── traits/
    └── userForm.php
``````php
namespace Nibiru\Module\Users\Plugin;
use Nibiru\Model\users;

class User {
    private users $usersModel;
    public function __construct() { $this->usersModel = new users(); }

    public function isAuthorized(): bool {
        return isset($_SESSION['auth']['user_id']);
    }

    public function findByLogin(string $login): ?array {
        return \Nibiru\Pdo::fetchRow(
            'SELECT * FROM users WHERE user_login = :login',
            [':login' => $login]
        ) ?: null;
    }
}
```
Cela maintient les contrôleurs légers (`$this->user->isAuthorized()`) tout en laissant le modèle généré inchangé.

## Trappes multidriver

L'adaptateur généré `Db` est spécifique au pilote. Si vous passez de MySQL à PostgreSQL, regénérez les modèles pour qu'ils étendent la classe de base appropriée :

- MySQL / PDO → `Nibiru\Adapter\MySQL\Db`
- PostgreSQL (libpq) → `Nibiru\Adapter\PostgreSQL\Db`
- ODBC → `Nibiru\Adapter\Odbc\Db`

Les mêmes assistants de requête, mais avec un adaptateur différent en arrière-plan.

## Quand sauter le générateur

Bases de données en lecture seule, systèmes de fournisseurs ou tout schéma que vous ne contrôlez pas : définissez `database = false`, rédigez manuellement des classes de modèle minimales qui correspondent aux colonnes que vous utilisez réellement, et validez-les.
