PHPackages                             wtframework/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. [Database &amp; ORM](/categories/database)
4. /
5. wtframework/orm

ActiveLibrary[Database &amp; ORM](/categories/database)

wtframework/orm
===============

What the Framework?! ORM

v0.2.1(1y ago)014MITPHPPHP ^8.2

Since Jan 20Pushed 1y ago1 watchersCompare

[ Source](https://github.com/wtframework/orm)[ Packagist](https://packagist.org/packages/wtframework/orm)[ RSS](/packages/wtframework-orm/feed)WikiDiscussions main Synced yesterday

READMEChangelog (4)Dependencies (2)Versions (5)Used By (0)

What the Framework?! ORM
========================

[](#what-the-framework-orm)

This library extends the [DBAL](https://github.com/wtframework/dbal) library to provide object–relational mapping.

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

[](#installation)

```
composer require wtframework/orm
```

Documentation
-------------

[](#documentation)

### Create a new model

[](#create-a-new-model)

Create a new model by extending the `WTFramework\ORM\Model` class.

```
use WTFramework\ORM\Model;

class User extends Model {}
```

By default the table name will be a pluralized form of the class name in snake case. For example, `class UserRole` will have a table name of `user_roles`. If you wish to specify the table name then include a `public const TABLE`.

```
class User extends Model
{
  public const TABLE = 'x_users';
}
```

By default the primary key will be the class name in snake case with a suffix of `_id`. For example, `class UserRole` will have a primary key of `user_role_id`. If you wish to specify the primary key then include a `public const PRIMARY_KEY`. This may be a string or an array (if a composite primary key).

```
class User extends Model
{
  public const PRIMARY_KEY = 'id';
}
```

By default the model will use the default database connection as defined in the [DBAL](https://github.com/wtframework/dbal) configuration settings. If you wish to specify the connection name then include a `public const CONNECTION`.

```
class User extends Model
{
  public const CONNECTION = 'mirror';
}
```

### Insert a record

[](#insert-a-record)

Use the `create` static method to create a new record passing its data as either a stdClass object or an array. This will return a new instance of the model.

```
$user = User::create(['user_id' => 1]);
```

### Select a record

[](#select-a-record)

Use the `get` static method to a select a record passing its primary key as a string, an integer, or an array (if a composite primary key).

```
$user = User::get(1);

$user = User::get([
  'id1' => 1,
  'id2' => 2,
]);
```

Use the `exists` method to determine if the record was found.

```
$user->exists();
```

Use the `require` static method to select a record and throw a `WTFramework\ORM\ModelNotFoundException` if the record was not found.

```
$user = User::require(1);

$user = User::require([
  'id1' => 1,
  'id2' => 2,
]);
```

### Update a record

[](#update-a-record)

Use the `save` method to update a record. You may set the data either by manually setting the model's properties or by passing its data as either a stdClass object or an array.

```
$user->name = 'Michael';

$user->save(['user_role_id' => 1]);
```

### Refresh a record

[](#refresh-a-record)

Use the `refresh` method to undo any changes that have not been saved to the database.

```
$user->name = 'Michael';

$user->refresh();
```

Use the `fresh` method to return a new instance of the record.

```
$user->name = 'Michael';

$fresh = $user->fresh();
```

### Querying the model

[](#querying-the-model)

You can query the model using any of the methods defined by the `SELECT` grammar of the [SQL](https://github.com/wtframework/sql) library. The results are then retrieved using either `get` for a single model or `all` for an array of models.

```
$users = User::where('user_role_id', 1)->all();
```

Models also provide a quick way to insert, update, delete, etc. Each of these methods return a fluent interface from the [DBAL](https://github.com/wtframework/dbal) library for generating SQL statements, automatically using the defined table.

```
User::select();
User::insert();
User::replace();
User::update();
User::delete();
User::truncate();
```

### Relationships

[](#relationships)

The ORM allows for creating `belongs to`, `has`, `has many`, `has through`, and `has many through` relationships.

```
use WTFramework\ORM\Model;
use WTFramework\ORM\Relationships\BelongsTo;
use WTFramework\ORM\Relationships\Has;
use WTFramework\ORM\Relationships\HasMany;
use WTFramework\ORM\Relationships\HasManyThrough;
use WTFramework\ORM\Relationships\HasThrough;

class User extends Model
{

  public function role(): BelongsTo
  {
    return $this->belongsTo(UserRole::class);
  }

  public function profile(): Has
  {
    return $this->has(Profile::class);
  }

  public function revisions(): HasMany
  {
    return $this->hasMany(UserRevision::class);
  }

  public function owner(): HasOneThrough
  {
    return $this->hasOneThrough(Owner::class, UserOwner::class);
  }

  public function permissions(): HasManyThrough
  {
    return $this->hasManyThrough(Permission::class, UserPermission::class);
  }

}
```

By default the records will be retrieved using the models' primary keys. If you require the relationships to use different column names then you can pass them as additional parameters.

```
class User extends Model
{

  public const PRIMARY_KEY = 'id';

  public function role(): BelongsTo
  {
    return $this->belongsTo(UserRole::class, local_key: 'role_id');
  }

  public function profile(): Has
  {
    return $this->has(Profile::class, foreign_key: 'user_id');
  }

  public function revisions(): HasMany
  {
    return $this->hasMany(UserRevision::class, foreign_key: 'user_id');
  }

  public function owner(): HasOneThrough
  {
    return $this->hasOneThrough(Owner::class, UserOwner::class, foreign_key: 'owner_id', pivot_local_key: 'user_id');
  }

  public function permissions(): HasManyThrough
  {
    return $this->hasManyThrough(Permission::class, UserPermission::class, foreign_key: 'permission_id', pivot_local_key: 'user_id');
  }

}
```

Use the relationship method name as a property to return the result of the relationship.

```
$role = $user->role->name;
```

When relationships are retrieved this way they will be cached. Use the `clearCache` method to clear the cache.

```
$user->clearCache();
```

If you call the relationship method directly then it will return an instance of `WTFramework\ORM\Query` allowing you to manipulate the results further.

```
$revisions = $user->revisions()->orderBy('created')->all();
```

By default relationships will be lazy loaded. This can lead to an N+1 query problem. To eager load the relationship you can call the `eager` method, passing in a string or an array of relationship names to eager load.

```
User::eager('revisions')->all();
```

You may also eager load by default by setting the `public const EAGER` array.

```
class User extends Model
{

  public const EAGER = ['revisions'];

  public function revisions(): HasMany
  {
    return $this->hasMany(UserRevision::class);
  }

}
```

When a relationship is eager loaded by default you can override this by calling the `lazy` method.

```
User::lazy('revisions')->where('user_id', 1)->get();
```

###  Health Score

26

—

LowBetter than 41% of packages

Maintenance33

Infrequent updates — may be unmaintained

Popularity6

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 91.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 ~77 days

Total

4

Last Release

662d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/120370615?v=4)[What the Framework?!](/maintainers/wtframework)[@wtframework](https://github.com/wtframework)

---

Top Contributors

[![MichaelRushton](https://avatars.githubusercontent.com/u/49325097?v=4)](https://github.com/MichaelRushton "MichaelRushton (11 commits)")[![wtframework](https://avatars.githubusercontent.com/u/120370615?v=4)](https://github.com/wtframework "wtframework (1 commits)")

###  Code Quality

TestsPest

### Embed Badge

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

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

###  Alternatives

[jdorn/sql-formatter

a PHP SQL highlighting library

3.9k117.2M118](/packages/jdorn-sql-formatter)[propel/propel1

Propel is an open-source Object-Relational Mapping (ORM) for PHP5.

8351.6M87](/packages/propel-propel1)[pgvector/pgvector

pgvector support for PHP

198741.5k12](/packages/pgvector-pgvector)[jfelder/oracledb

Oracle DB driver for Laravel

11518.4k](/packages/jfelder-oracledb)

PHPackages © 2026

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