PHPackages                             ez-php/orm - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. ez-php/orm

ActiveLibrary[Framework](/categories/framework)

ez-php/orm
==========

ORM module for the ez-php framework — Active Record style models with a fluent query builder and schema builder

1.11.1(1mo ago)03.3k↓90%1MITPHPPHP ^8.5CI passing

Since Mar 15Pushed 1mo agoCompare

[ Source](https://github.com/ez-php/orm)[ Packagist](https://packagist.org/packages/ez-php/orm)[ Docs](https://github.com/ez-php/orm)[ RSS](/packages/ez-php-orm/feed)WikiDiscussions main Synced 3w ago

READMEChangelogDependencies (20)Versions (47)Used By (1)

ez-php/orm
==========

[](#ez-phporm)

ORM module for the [ez-php framework](https://github.com/ez-php/framework) — Data Mapper pattern with `Entity`, `AbstractRepository`, a fluent `QueryBuilder`, and a `Schema` builder.

[![CI](https://github.com/ez-php/orm/actions/workflows/ci.yml/badge.svg)](https://github.com/ez-php/orm/actions/workflows/ci.yml)

Requirements
------------

[](#requirements)

- PHP 8.5+
- ext-pdo
- ez-php/framework 0.\*

Installation
------------

[](#installation)

```
composer require ez-php/orm
```

Setup
-----

[](#setup)

Register the service providers:

```
$app->register(\EzPhp\Orm\EntityServiceProvider::class);
$app->register(\EzPhp\Orm\Schema\SchemaServiceProvider::class);
```

Usage
-----

[](#usage)

### Defining an entity

[](#defining-an-entity)

```
use EzPhp\Orm\Entity;

class User extends Entity
{
    protected static string $table      = 'users';
    protected static bool   $timestamps = true;
    protected static array  $fillable   = ['name', 'email'];
    protected static array  $casts      = ['age' => 'int'];
}
```

### Defining a repository

[](#defining-a-repository)

```
use EzPhp\Orm\AbstractRepository;

/**
 * @extends AbstractRepository
 */
class UserRepository extends AbstractRepository
{
    protected function entityClass(): string
    {
        return User::class;
    }

    public function findByEmail(string $email): ?User
    {
        return $this->findOneBy('email', $email);
    }

    public function activeUsers(): array
    {
        return $this->query()->where('active', true)->orderBy('name')->get();
    }
}
```

### Persisting

[](#persisting)

```
$repo = $app->make(UserRepository::class);

// INSERT
$user = new User(['name' => 'Alice', 'email' => 'alice@example.com']);
$repo->save($user);

// UPDATE (only dirty columns)
$user->name = 'Bob';
$repo->save($user);

// DELETE
$repo->delete($user);
```

### Querying

[](#querying)

```
$user  = $repo->find(1);
$all   = $repo->findAll();
$alice = $repo->findByEmail('alice@example.com');
$page  = $repo->query()->where('active', true)->paginate(perPage: 15, page: 1);
```

### Soft deletes

[](#soft-deletes)

```
class Post extends Entity
{
    protected static string $table       = 'posts';
    protected static bool   $softDeletes = true;
}
```

```
$repo->delete($post);           // sets deleted_at — row stays in the DB
$post->trashed();               // true after soft delete

// Include soft-deleted rows
$all = $repo->query()->withTrashed()->get();
$deleted = $repo->query()->onlyTrashed()->get();
```

### Relations

[](#relations)

Define relation helpers on the repository, then call them on an entity:

```
class PostRepository extends AbstractRepository
{
    protected function entityClass(): string { return Post::class; }

    public function author(Post $post): EntityBelongsTo
    {
        return $this->belongsTo(UserRepository::class, 'user_id', 'id');
    }
}

// Lazy load
$author = $postRepo->author($post)->getResult();

// Eager load (avoids N+1)
$posts = $postRepo->query()->with('author')->get();
```

### Custom casts

[](#custom-casts)

```
use EzPhp\Orm\CastableInterface;

class Money implements CastableInterface
{
    public function __construct(private readonly int $cents) {}

    public static function castFrom(mixed $value): static
    {
        return new self((int) $value);
    }

    public function castTo(): mixed
    {
        return $this->cents;
    }
}

class Product extends Entity
{
    protected static array $casts = ['price' => Money::class];
}
```

### Entity lifecycle observers

[](#entity-lifecycle-observers)

Attach observers to a repository to react to create/update/delete events:

```
use EzPhp\Orm\EntityObserverInterface;
use EzPhp\Orm\ObservableRepositoryTrait;

class AuditObserver implements EntityObserverInterface
{
    public function creating(object $entity): void {}
    public function created(object $entity): void { /* log insert */ }
    public function updating(object $entity): void {}
    public function updated(object $entity): void { /* log update */ }
    public function deleting(object $entity): void {}
    public function deleted(object $entity): void { /* log delete */ }
}

class UserRepository extends AbstractRepository
{
    use ObservableRepositoryTrait;
    // ...
}

$repo->observe(new AuditObserver());
```

The `*ing` hooks fire before the DB operation; `*ed` hooks fire after.

### Schema builder

[](#schema-builder)

```
use EzPhp\Orm\Schema\Schema;

Schema::create('users', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->string('email')->unique();
    $table->timestamps();
});

Schema::table('users', function (Blueprint $table) {
    $table->string('phone')->nullable();
});

Schema::drop('old_table');
```

### Console commands

[](#console-commands)

CommandDescription`make:entity`Scaffolds an `Entity` subclass in `src/Entities/``make:repository`Scaffolds an `AbstractRepository` subclass in `src/Repositories/`Classes
-------

[](#classes)

ClassDescription`Entity`Abstract Data Mapper entity base; attributes, casts, fillable guards, relation storage`AbstractRepository`Abstract repository base; INSERT/UPDATE/DELETE, dirty tracking, relations, eager-load`EntityObserverInterface`Lifecycle hook contract: `creating/created/updating/updated/deleting/deleted``ObservableRepositoryTrait`Adds observer support to a repository; fires hooks around `save()` and `delete()``EntityQueryBuilder`Typed fluent query builder for entities; `with()`, `withCount()`, `paginate()``EntityServiceProvider`Calls `Entity::setDatabase($db)` in `boot()``Hydrator`Converts raw DB rows → Entity instances and Entity attributes → storage arrays`CastableInterface`Interface for custom value-object casts: `castFrom()`/`castTo()``DuplicateKeyException`Thrown by `save()` on duplicate-key violations`Paginator`Immutable page-of-results value object`QueryBuilder`Fluent SQL builder for raw rows; all WHERE/JOIN/ORDER/LIMIT/aggregates/paginate/chunk/cache`EntityHasMany`One-to-many relation (FK on related entity)`EntityHasOne`One-to-one relation (FK on related entity)`EntityBelongsTo`Inverse of HasMany/HasOne (FK on owning entity)`EntityBelongsToMany`Many-to-many relation via pivot table`Schema`DDL façade: `create()`, `table()`, `drop()`, `dropIfExists()`, `hasTable()``Blueprint`Column and constraint builder for `CREATE TABLE` and `ALTER TABLE`License
-------

[](#license)

MIT — [Andreas Uretschnig](mailto:andreas.uretschnig@gmail.com)

###  Health Score

50

—

FairBetter than 95% of packages

Maintenance91

Actively maintained with recent releases

Popularity21

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity64

Established project with proven stability

 Bus Factor1

Top contributor holds 92.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

46

Last Release

43d ago

Major Versions

0.9.3 → 1.0.02026-03-24

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/122030400?v=4)[AU9500](/maintainers/AU9500)[@AU9500](https://github.com/AU9500)

---

Top Contributors

[![AU9500](https://avatars.githubusercontent.com/u/122030400?v=4)](https://github.com/AU9500 "AU9500 (152 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (12 commits)")

---

Tags

phpframeworkdatabaseormactive-recordquery builderschema builderez-php

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/ez-php-orm/health.svg)

```
[![Health](https://phpackages.com/badges/ez-php-orm/health.svg)](https://phpackages.com/packages/ez-php-orm)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
