nixphp / orm
NixPHP ORM Plugin.
Requires
- php: >=8.3
- ext-pdo: *
- nixphp/database: ^v0.1.1
- nixphp/framework: ^v0.1.2
Requires (Dev)
- phpunit/php-code-coverage: ^12.1
- phpunit/phpunit: ^12.1
This package is auto-updated.
Last update: 2026-07-28 18:52:22 UTC
README
nixphp/orm
Minimalistic object mapper for your NixPHP application.
This plugin adds basic ORM support to NixPHP:
lightweight, readable, and ideal for small to medium use cases.
It supports nested entity saving (including pivot tables),
auto-discovery of related entities, and repository-based lazy-loading.
🧩 Part of the official NixPHP plugin collection.
Use it if you want structured object handling – but without the complexity of full-stack ORM systems.
📦 Features
- ✅ Save any entity using
em()->save($entity) - ✅ Detects and stores relations automatically
- ✅ Supports
Many-to-One,One-to-Many, andMany-to-Manyout of the box - ✅ Uses simple PHP classes, no annotations or metadata
- ✅ Makes repository-based lazy-loading easy to implement in regular
getX()methods - ✅ Comes with a clean
AbstractRepositoryfor queries
📥 Installation
composer require nixphp/orm
nixphp/database is installed automatically as a dependency.
🛠 Configuration
This plugin uses the shared PDO instance from nixphp/database.
Make sure your /app/config.php contains a working database section.
Example: MySQL
return [ // ... 'database' => [ 'driver' => 'mysql', 'host' => '127.0.0.1', 'database' => 'myapp', 'username' => 'root', 'password' => '', 'charset' => 'utf8mb4', ] ];
Example: SQLite
return [ // ... 'database' => [ 'driver' => 'sqlite', 'database' => __DIR__ . '/../storage/database.sqlite', ] ];
Or for in-memory usage (great for testing):
return [ // ... 'database' => [ 'driver' => 'sqlite', 'database' => ':memory:', ] ];
🧩 Usage
Define your models
Models extend AbstractModel, which already implements EntityInterface via
EntityTrait.
use NixPHP\ORM\Model\AbstractModel; use function NixPHP\ORM\repo; class Product extends AbstractModel { protected ?int $id = null; protected string $name = ''; protected ?int $category_id = null; protected ?Category $category = null; protected array $tags = []; public function getName(): string { return $this->name; } public function setName(string $name): void { $this->name = $name; } public function setCategory(Category $category): void { $this->category = $category; } public function addTag(Tag $tag): void { $this->tags[] = $tag; } public function getTags(): array { if ($this->tags === [] && $this->id !== null) { $this->tags = repo(TagRepository::class) ->findByPivot(Product::class, $this->id); } return $this->tags; } public function getCategory(): ?Category { if ($this->category === null && $this->category_id !== null) { $this->category = repo(CategoryRepository::class) ->findOneBy('id', $this->category_id); } return $this->category; } }
Saving data
use function NixPHP\ORM\em; use function NixPHP\ORM\repo; $category = repo(CategoryRepository::class)->findOrCreateBy('name', 'Books'); $tagA = repo(TagRepository::class)->findOrCreateBy('name', 'Bestseller'); $tagB = repo(TagRepository::class)->findOrCreateBy('name', 'Limited'); $product = new Product(); $product->setName('NixPHP for Beginners'); $product->setCategory($category); $product->addTag($tagA); $product->addTag($tagB); em()->save($product);
Reading data
use function NixPHP\ORM\repo; $product = repo(ProductRepository::class)->findOneBy('id', 1); if ($product !== null) { echo $product->getName(); print_r($product->getCategory()); print_r($product->getTags()); }
The getters above implement lazy-loading explicitly through repositories.
When saving, entity-object properties and arrays of entities are discovered
automatically. A child foreign key follows the <parent>_id convention; pivot
table names are built from the two singular table names in alphabetical order.
For a custom pivot name, define a public mapping on either entity:
public array $pivotTables = [ Tag::class => 'article_tags', ];
📚 Philosophy
This ORM is intentionally small and predictable. It provides just enough structure to manage entities and relations – without introducing complex abstractions or hidden behavior.
If you need validation, eager loading, event hooks, or advanced query building, you can integrate any larger ORM of your choice alongside it.
✅ Requirements
- PHP >= 8.3
nixphp/framework^0.1.2nixphp/database^0.1.1
📄 License
MIT License.