nilsframework / nils-orm
ORM léger pour NilsFramework — CRUD complet, relations, validation, eager loading et pagination.
Requires
- php: >=8.1
- nilsframework/nils-database: ^1.0
This package is not auto-updated.
Last update: 2026-04-20 09:06:46 UTC
README
ORM léger pour NilsFramework — CRUD complet, relations, validation, eager loading et pagination.
📋 Table des matières
- Installation
- Créer un modèle
- Schema de validation
- Visibilité des champs
- CRUD
- Filtres avancés
- Pagination
- Relations
- Eager Loading
- toArray()
- save()
Installation
composer require nilsframework/nils-orm
nilsframework/nils-databaseest installé automatiquement comme dépendance. Si vous utilisez déjànilsframework/nilsetnilsframework/nils-databasedans votre projet,nils-orms'y intègre sans conflit.
Avec le framework complet
# Installation complète recommandée
composer require nilsframework/nils
composer require nilsframework/nils-database
composer require nilsframework/nils-orm
Standalone
# nils-orm seul — nils-database est tiré automatiquement
composer require nilsframework/nils-orm
Créer un modèle
use core\Modele;
class Groupe extends Modele
{
protected static string $table = 'tnt_groupes';
protected static string $primaryKey = 'id';
protected static array $guarded = ['created_at', 'updated_at'];
protected static array $hidden = [];
protected static array $visible = [];
protected static array $schema = [
'nom' => [
'type' => 'string',
'required' => true,
'min' => 2,
'max' => 100,
'messages' => [
'required' => "Le nom du groupe est requis.",
],
],
'montant_cotisation' => [
'type' => 'float',
'required' => true,
'min' => 1,
],
'frequence_jours' => [
'type' => 'int',
'required' => true,
],
'date_debut' => [
'type' => 'date',
'required' => true,
],
'description' => [
'type' => 'string',
'required' => false,
],
];
public function participations(): array
{
return $this->hasMany(Participation::class, 'groupe_id');
}
public function cycles(): array
{
return $this->hasMany(Cycle::class, 'groupe_id', orderBy: 'numero ASC');
}
public function admin(): mixed
{
return $this->belongsTo(Admin::class, 'admin_id');
}
}
Les champs présents en base de données mais absents du
$schemasont acceptés sans erreur.
Schema de validation
Chaque champ du schema accepte les règles suivantes :
| Règle | Type | Description |
|---|---|---|
type | string | string, int, float, bool, date, datetime, enum |
required | bool | Champ obligatoire |
min | int/float | Longueur min (string) ou valeur min (numérique) |
max | int/float | Longueur max (string) ou valeur max (numérique) |
email | bool | Validation email |
unique | bool | Unicité en base de données |
hash | bool | Hash automatique bcrypt |
default | mixed | Valeur par défaut si absent |
values | array | Valeurs autorisées pour enum |
messages | array | Messages d'erreur personnalisés |
protected static array $schema = [
'email' => [
'type' => 'string',
'required' => true,
'email' => true,
'unique' => true,
'messages' => [
'required' => "L'email est requis.",
'invalid' => "L'email est invalide.",
'unique' => "Cet email est déjà utilisé.",
],
],
'password' => [
'type' => 'string',
'required' => true,
'min' => 8,
'hash' => true,
],
'role' => [
'type' => 'enum',
'values' => ['admin', 'membre', 'moderateur'],
],
'actif' => [
'type' => 'bool',
'default' => true,
],
'date_naissance' => [
'type' => 'date', // Y-m-d
],
'created_at' => [
'type' => 'datetime', // Y-m-d H:i:s
],
];
Visibilité des champs
$hidden — masquer des champs dans toArray()
protected static array $hidden = ['password', 'remember_token'];
$visible — n'afficher que ces champs dans toArray()
protected static array $visible = ['id', 'nom', 'email'];
// Si $visible est défini → seuls ces champs apparaissent (prioritaire sur $hidden)
$guarded — champs jamais envoyés en INSERT/UPDATE
protected static array $guarded = ['created_at', 'updated_at'];
// La clé primaire est toujours exclue automatiquement
$fillable — champs autorisés en écriture
protected static array $fillable = ['nom', 'email', 'password'];
// Si vide → tous les champs sauf $guarded et la PK sont autorisés
CRUD
get()
Récupère un élément par ID ou une liste filtrée.
// Par ID — retourne l'objet ou lève NotFoundException
$groupe = Groupe::get(1);
// Tous les enregistrements
$groupes = Groupe::get();
// Avec ORDER BY
$groupes = Groupe::get(null, 'created_at DESC');
// Avec LIMIT
$groupes = Groupe::get(null, 'created_at DESC', 5);
// Avec filtres
$groupes = Groupe::get(['admin_id' => 3]);
post()
Crée un nouvel enregistrement avec validation complète.
$groupe = Groupe::post([
'admin_id' => 1,
'nom' => 'Tontine 2024',
'montant_cotisation' => 5000,
'frequence_jours' => 30,
'date_debut' => '2024-01-01',
'description' => 'Notre tontine annuelle',
]);
echo $groupe->id; // ID généré automatiquement
echo $groupe->nom; // "Tontine 2024"
put()
Remplace entièrement un enregistrement existant.
$groupe = Groupe::put(1, [
'nom' => 'Nouveau nom',
'montant_cotisation' => 10000,
'frequence_jours' => 15,
'date_debut' => '2024-06-01',
]);
patch()
Met à jour partiellement — valide uniquement les champs fournis.
// Un seul champ
$groupe = Groupe::patch(1, ['nom' => 'Nom modifié']);
// Plusieurs champs
$groupe = Groupe::patch(1, [
'montant_cotisation' => 7500,
'description' => 'Description mise à jour',
]);
delete()
Supprime et retourne l'objet supprimé.
$groupe = Groupe::delete(1);
echo $groupe->nom; // "Tontine 2024" — l'objet est retourné avant suppression
Filtres avancés
// Égalité
$groupes = Groupe::get(['admin_id' => 5]);
// Valeur nulle
$groupes = Groupe::get(['description' => null]);
// → WHERE description IS NULL
// LIKE
$groupes = Groupe::get(['nom_like' => 'tontine']);
// → WHERE nom LIKE '%tontine%'
// Min / Max
$groupes = Groupe::get(['montant_cotisation_min' => 1000]);
// → WHERE montant_cotisation >= 1000
$groupes = Groupe::get(['montant_cotisation_max' => 10000]);
// → WHERE montant_cotisation <= 10000
// Combinés
$groupes = Groupe::get([
'admin_id' => 3,
'nom_like' => 'ton',
'montant_cotisation_min' => 1000,
'montant_cotisation_max' => 50000,
], 'created_at DESC');
Pagination
$result = Groupe::get([
'admin_id' => 3,
'pagination' => true,
'page' => 1,
'limit' => 10,
], 'created_at DESC');
// Résultat
// [
// 'total' => 45,
// 'page' => 1,
// 'limit' => 10,
// 'pages' => 5,
// 'items' => [ Groupe, Groupe, ... ]
// ]
foreach ($result['items'] as $groupe) {
echo $groupe->nom;
}
Relations
hasOne
Ce modèle possède un seul autre modèle.
// Dans le modèle Admin
public function session(): mixed
{
return $this->hasOne(AdminSession::class, 'admin_id');
}
// Utilisation
$admin = Admin::get(1);
$session = $admin->session();
hasMany
Ce modèle possède plusieurs autres modèles.
// Dans le modèle Groupe
public function participations(): array
{
return $this->hasMany(Participation::class, 'groupe_id');
}
public function cycles(): array
{
return $this->hasMany(Cycle::class, 'groupe_id', orderBy: 'numero ASC');
}
// Utilisation
$groupe = Groupe::get(1);
$participations = $groupe->participations();
$cycles = $groupe->cycles();
belongsTo
Ce modèle appartient à un autre modèle.
// Dans le modèle Participation
public function groupe(): mixed
{
return $this->belongsTo(Groupe::class, 'groupe_id');
}
public function utilisateur(): mixed
{
return $this->belongsTo(Utilisateur::class, 'utilisateur_id');
}
// Utilisation
$participation = Participation::get(1);
$groupe = $participation->groupe();
$utilisateur = $participation->utilisateur();
belongsToMany
Relation N-N via table pivot.
// Dans le modèle Utilisateur
public function groupes(): array
{
return $this->belongsToMany(
Groupe::class,
'tnt_participations', // table pivot
'utilisateur_id', // FK locale dans le pivot
'groupe_id' // FK liée dans le pivot
);
}
// Utilisation
$utilisateur = Utilisateur::get(1);
$groupes = $utilisateur->groupes();
Eager Loading
Charge les relations en même temps que l'objet principal.
// Charger un groupe avec ses participations et cycles
$groupe = Groupe::with(['participations', 'cycles'])->get(1);
// Les relations sont accessibles via toArray(true)
$data = $groupe->toArray(true);
// [
// 'id' => 1,
// 'nom' => 'Tontine 2024',
// 'participations' => [ [...], [...] ],
// 'cycles' => [ [...], [...] ],
// ]
// Ou directement
$groupe->participations; // tableau de Participation
$groupe->cycles; // tableau de Cycle
toArray()
$groupe = Groupe::get(1);
// Sans relations
$data = $groupe->toArray();
// ['id' => 1, 'nom' => 'Tontine 2024', ...]
// Avec relations chargées (eager ou lazy)
$groupe->chargerRelations(['participations', 'cycles']);
$data = $groupe->toArray(true);
// ['id' => 1, 'nom' => '...', 'participations' => [...], 'cycles' => [...]]
save()
Sauvegarde manuellement un objet — INSERT si pas de PK, UPDATE sinon.
// Modifier un attribut et sauvegarder
$groupe = Groupe::get(1);
$groupe->nom = "Nouveau nom";
$groupe->save();
// Créer manuellement
$groupe = new Groupe();
$groupe->hydrater([
'admin_id' => 1,
'nom' => 'Tontine manuelle',
'montant_cotisation' => 5000,
'frequence_jours' => 30,
'date_debut' => '2024-01-01',
]);
$groupe->save();
echo $groupe->id; // ID généré
Licence
MIT — © NilsFramework