nils-framework/nils-orm
最新稳定版本:v1.0
Composer 安装命令:
composer require nils-framework/nils-orm
包简介
ORM ActiveRecord léger avec champs typés, validation par règles, relations, Eager Loading, Identity Map et Serializer pour le framework NILS
README 文档
README
Le composant nils-orm est la couche de mapping objet-relationnel (ORM) légère du framework PHP NILS. Construit au-dessus de nils-database, il fournit un pattern ActiveRecord sans attributs ni annotations : les modèles déclarent leur structure via une méthode definition() explicite, en parfaite cohérence avec la philosophie du framework.
Il embarque un système de champs typés, un moteur de validation par règles, des relations (One-to-Many, Many-to-One, Many-to-Many), l'Eager Loading anti N+1, une Identity Map, la pagination automatique et la génération de schéma SQL.
🚀 Fonctionnalités Clés
- Modèles ActiveRecord déclaratifs : Structure définie par code (
definition()), sans attributs PHP 8 ni configuration externe. - 13 types de champs typés :
StringField,IntField,FloatField,BooleanField,DateField,DateTimeField,EmailField,PasswordField,TextField,JsonField,UuidField,ForeignKeyField... avec cast automatique PHP ↔ SQL. - Validation par règles (Fluent) :
Unique,Exists,In,Min,Max,Regex— extensibles viaRuleInterface. - Relations complètes :
BelongsTo(Many-to-One),HasMany(One-to-Many) etBelongsToMany(Many-to-Many via table pivot), avec chargement paresseux (Lazy Loading) par accès magique. - Eager Loading (
with()) : Résolution groupée des relations en une seule requêteWHERE INpour éliminer le problème des requêtes N+1. - Identity Map : Cache d'instances en mémoire garantissant qu'une ligne SQL correspond toujours au même objet PHP durant la requête.
- Repository Pattern : Couche d'accès haut niveau — CRUD rapide, recherche textuelle, insertion de masse (Bulk Insert), transactions et pagination.
- Serializer (inspiré de Django REST Framework) : Validation des données entrantes et extraction structurée des données sortantes pour vos APIs.
- Schema Engine : Génération automatique des tables, index et contraintes de clés étrangères à partir des définitions de modèles.
- Hooks de cycle de vie :
beforeSave(),afterSave(),beforeDelete()pour greffer votre logique métier. - Timestamps automatiques : Gestion native de
created_at/updated_at.
📦 Installation
Installez le module via Composer :
composer require nils-framework/nils-orm
Note : Ce package requiert
nils-framework/nils-database(drivers, QueryBuilder, transactions) et s'intègre nativement au middleware d'exceptions denils-coreviaValidationException.
🛠️ Utilisation de Base
1. Définir un Modèle
use NilsOrm\Model;
use NilsOrm\Fields\StringField;
use NilsOrm\Fields\EmailField;
use NilsOrm\Fields\PasswordField;
use NilsOrm\Fields\BooleanField;
use NilsOrm\Rules\Unique;
use NilsOrm\Rules\Min;
class User extends Model
{
protected static string $table = 'users';
public static function definition(): array
{
return [
'nom' => new StringField(),
'email' => (new EmailField())->addRule(new Unique()),
'password' => (new PasswordField())->addRule(new Min(8)),
'actif' => new BooleanField(),
];
}
}
2. Opérations CRUD
// Création
$user = new User(['nom' => 'Traore', 'email' => 'traore@nils.dev']);
$user->save(); // Validation automatique avant insertion
// Lecture (avec Identity Map)
$user = User::find(1);
// Mise à jour
$user->nom = 'Traore N.';
$user->save();
// Suppression
$user->delete();
3. Déclarer des Relations
use NilsOrm\Relations\HasMany;
use NilsOrm\Relations\BelongsTo;
use NilsOrm\Relations\BelongsToMany;
class Article extends Model
{
public static function relations(): array
{
return [
'auteur' => new BelongsTo(User::class, 'user_id'),
'categories' => new BelongsToMany(Category::class, 'article_category', 'article_id', 'category_id'),
];
}
}
// Accès paresseux (Lazy Loading)
$article = Article::find(1);
echo $article->auteur->nom; // Charge le parent à la demande
$categories = $article->categories; // Charge via la table pivot
4. Repository, Recherche et Pagination
use NilsOrm\Repository;
$repo = new Repository(Article::class);
// Eager Loading : 2 requêtes au total, quel que soit le nombre d'articles
$pagination = $repo->with(['auteur', 'categories'])->paginate(page: 1, perPage: 15);
// Recherche textuelle filtrée
$qb = $repo->search('framework', ['titre', 'contenu'], ['actif' => 1]);
$resultats = $repo->paginate($qb, page: 2);
// Réponse API standardisée
return $pagination->toArray();
// ['items' => [...], 'meta' => ['total' => ..., 'current_page' => ..., 'per_page' => ..., 'last_page' => ...]]
5. Transactions et Insertion de Masse
$repo->transaction(function () use ($repo) {
$repo->create(['titre' => 'Article 1']);
$repo->createMany([
['titre' => 'Article 2', 'user_id' => 1],
['titre' => 'Article 3', 'user_id' => 1],
]);
}); // Rollback automatique en cas d'exception
6. Valider les Données Entrantes (Serializer)
use NilsOrm\Serializer;
class UserSerializer extends Serializer
{
public function fields(): array
{
return (User::definition()); // Réutilisation directe des champs du modèle
}
}
// Dans un contrôleur NILS
$serializer = new UserSerializer(data: $body);
$donnees = $serializer->validateOrFail(); // Lève ValidationException → réponse 400 JSON structurée
7. Générer le Schéma SQL
use NilsOrm\SchemaEngine;
SchemaEngine::createTableFromModel(User::class);
SchemaEngine::createTableFromModel(Article::class);
// Tables, index, contraintes UNIQUE et clés étrangères créés automatiquement
📦 Architecture du Dépôt
src/
├── Exceptions/
│ └── ValidationException.php # Exception 400 structurée par champ
└── NilsOrm/
├── Fields/ # 13 types de champs typés (cast + SQL)
├── Relations/ # BelongsTo, HasMany, BelongsToMany
├── Rules/ # Unique, Exists, In, Min, Max, Regex
├── Model.php # ActiveRecord (CRUD, hooks, lazy loading)
├── Repository.php # Accès haut niveau (Eager Loading, transactions)
├── IdentityMap.php # Cache d'instances en mémoire
├── Pagination.php # Résultats paginés prêts pour JSON
├── SchemaEngine.php # Génération DDL depuis les modèles
└── Serializer.php # Validation entrante / extraction sortante
⚙️ Cache et Cohérence
L'Identity Map garantit que deux appels à User::find(1) au sein d'une même requête HTTP retournent la même instance PHP, sans requête SQL redondante. Le registre est automatiquement synchronisé lors des opérations save() et peut être vidé manuellement :
use NilsOrm\IdentityMap;
IdentityMap::clear(); // Réinitialisation complète du registre
📄 Licence
Ce projet est distribué sous licence MIT. Développé avec passion par Traore.
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 2
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-09