PHPackages                             ronanchilvers/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. ronanchilvers/orm

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

ronanchilvers/orm
=================

Simple database ORM implementation

2.1(3y ago)02.2k[1 issues](https://github.com/ronanchilvers/orm/issues)[1 PRs](https://github.com/ronanchilvers/orm/pulls)MITPHPPHP ^8.0CI failing

Since May 10Pushed 2y ago2 watchersCompare

[ Source](https://github.com/ronanchilvers/orm)[ Packagist](https://packagist.org/packages/ronanchilvers/orm)[ RSS](/packages/ronanchilvers-orm/feed)WikiDiscussions master Synced 2w ago

READMEChangelog (10)Dependencies (7)Versions (46)Used By (0)

ronanchilvers/orm
=================

[](#ronanchilversorm)

[![Actions Status](https://github.com/ronanchilvers/orm/workflows/Unit%20Tests/badge.svg)](https://github.com/ronanchilvers/orm/actions)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/ade3dc42b09d220ddadfbfa23aacf162d4e846d02cbf22f9a4b57c47e0382c0d/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f726f6e616e6368696c766572732f6f726d2f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/ronanchilvers/orm/?branch=master)

`orm` is a small and simple database layer implementing the [active record](https://en.wikipedia.org/wiki/Active_record_pattern) pattern. Its aim is to be simple, fast and useful. It relies on the \[clancats hydrahon\] query builder for database query access.

Overview
--------

[](#overview)

### Things it does

[](#things-it-does)

- PDO underneath so should work with any PDO compatible database
- Provides a full query builder interface using [clancats/hydrahon](https://clancats.io/hydrahon/master/)
- Supports full save, destroy, update, insert functionality through the active record implementation
- Supports model finder objects to help avoid 'fat model' syndrome
- Supports fine grained model hooks for precise control of model lifecycle data
- Supports model validation using [respect/validation](https://github.com/respect/validation)
- Simple relationship handling - belongsTo, hasMany, hasOne
- Configurable data type conversion for model properties

### Things it does NOT do

[](#things-it-does-not-do)

- Migrations - you can use whatever you like to manage your schema. We recommend [phinx](https://phinx.org/)
- Multiple database connections - currently `orm` only supports a single PDO connection.

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

[](#installation)

You'll need at least PHP7.0 to use the library. The recommended way to install is using [composer](https://getcomposer.org/):

```
composer install ronanchilvers/orm
```

Configuring the database
------------------------

[](#configuring-the-database)

Since `orm` uses PDO, it's up to you how you create and instantiate your PDO object. This will probably be in your bootstrap somewhere. Once your PDO object is available you will need to give it to `orm`. Here's an example:

```
$pdo = new PDO('sqlite::memory:');

Ronanchilvers\Orm\Orm::setConnection($pdo);
```

Clearly you will almost certainly not be using a `:memory:` DSN in practice. However you create your PDO object, the crucial point here is that you call `Orm::setConnection`to provide `orm` with your connection object.

Basic usage
-----------

[](#basic-usage)

`orm` doesn't make any pre-judgments about your database schema. When building models from a database it assumes it maps columns to properties and when saving it assumes that any property has a corresponding database table column. Its up to you to make sure the data makes sense.

Here we assume that we have a database table that looks like the following. We're using MySQL / MariaDB syntax here but whatever PDO supports should be fine.

```
CREATE TABLE `books` (
  `book_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `book_author` int(11) NOT NULL,
  `book_name` varchar(1024) NOT NULL DEFAULT '',
  `book_created` datetime DEFAULT CURRENT_TIMESTAMP,
  `book_updated` datetime DEFAULT NULL,
  PRIMARY KEY (`book_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```

### Defining a model

[](#defining-a-model)

First create your model class. It should extend the `Ronanchilvers\Orm\Model`class. As with many [active record](https://en.wikipedia.org/wiki/Active_record_pattern) implementations we assume here that the table has a plural name (books) and its corresponding model class will have a singular name (book).

```
class Book extends Model
{}
```

If your columns have no column prefix, that's all you need to do. The table name will be inferred from the class name. If however, like the example above, you have column prefixes then you can tweak your model to suit.

```
class Book extends Model
{
    static protected $columnPrefix = 'book';
}
```

Similarly if your table doesn't map to the model name you can specufy that too.

```
class Book extends Model
{
    static protected $table        = 'my_books_table';
    static protected $columnPrefix = 'book';
}
```

Now you're ready to use the model.

### Finding models

[](#finding-models)

`orm` supports a query builder interface provided by [clancats/hydrahon](https://clancats.io/hydrahon/master/). In order to retrieve models from the database, first obtain a finder object.

```
$finder = Orm::finder(Book::class);
```

Then you can use the finder object to retrieve models.

```
$books = $finder->all();
```

There are several standard finder methods you can use:

```
// Get all the records in one go
$books = $finder->all();

// Get the third page of models when there are 30 records per page
// (10 per page is the default)
$books = $finder->all(3, 30);

// Get a specific model by its primary key, here assumed to be numeric
$book = $finder->one(23);
```

You can use the full query builder to gain more control over the query:

```
// Get all the books for author id 20
$books = $finder->select()->where('book_author', 20);

// Get all books added since last week - here we're using the excellent Carbon wrapper
// for DateTime
$recentBooks = $finder->select()->where('book_created', '>', Carbon::now()->subWeek());
```

You can read more about the capabilities of the query builder over at the [clancats/hydrahon](https://clancats.io/hydrahon/master/) site.

If you want complete control over the SQL that is executed you can do:

```
$sql = "SELECT *
FROM books
  LEFT JOIN authors ON author_id = book_author
WHERE author_name LIKE :name
  AND author_created < :created";
$params = [
  'name'    => 'Fred%',
  'created' => Carbon::now()->subYear()->format('Y-m-d H:i:s'),
];
$books = $finder->query($sql, $params);
```

#### Custom Finder Classes

[](#custom-finder-classes)

By default `Orm::finder` will give you back a vanilla `Ronanchilvers\Orm\Finder` object tied to given model class. However you can also override the finder class for a given model by setting the `$finder` static property on your model. This can be very useful if you want to add custom find methods (for example).

Let's imagine you've created a `BookFinder` class:

```
class BookFinder extends Finder
{
    public function forAuthorId(int $id): array
    {
        return $this
          ->select()
          ->where(Book::prefix('author'), $id)
          ->execute();
    }
}
```

You can see that we've created a subclass of the default finder and we've added a `forAuthorId` method which returns an array of books for a given author id.

Then we tell the model about our new finder class:

```
class Book extends Model
{
    static protected $finder = BookFinder::class;
}
```

and then finally you're readdy to use it:

```
// $finder will be an instance of BookFinder here
$finder = Orm::finder(Book::class);
$authors = $finder->forAuthorId(2);
```

### Persistence

[](#persistence)

Saving a model back to the database is simply a matter of calling the `save` method.

```
$finder = Orm::finder(Book::class);
$book = $finder->one(23);
$book->save();
```

Similarly destroying a model is also simple:

```
$book->delete();
```

### Accessing model data

[](#accessing-model-data)

As in any active record implementation, database table columns are expressed as properties on the model instance. Consequently data can be accessed by accessing those properties.

```
$finder = Orm::finder(Book::class);
$book = $finder->one(72);
echo $book->name;
```

###  Health Score

35

—

LowBetter than 77% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity17

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity77

Established project with proven stability

 Bus Factor1

Top contributor holds 99.2% 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 ~34 days

Recently: every ~289 days

Total

43

Last Release

1171d ago

Major Versions

0.15 → 1.02019-09-05

1.11 → 2.02022-11-25

PHP version history (3 changes)0.1PHP ^7.0

0.14PHP ^7.1.8

2.0PHP ^8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/f6d7178329cb95270cfb9c807c3d2a6485d0f856c3d81cfe432e469e5f958748?d=identicon)[ronanchilvers](/maintainers/ronanchilvers)

---

Top Contributors

[![ronanchilvers](https://avatars.githubusercontent.com/u/87890?v=4)](https://github.com/ronanchilvers "ronanchilvers (120 commits)")[![scrutinizer-auto-fixer](https://avatars.githubusercontent.com/u/6253494?v=4)](https://github.com/scrutinizer-auto-fixer "scrutinizer-auto-fixer (1 commits)")

---

Tags

activerecordorm

###  Code Quality

TestsPHPUnit

### Embed Badge

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

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

###  Alternatives

[directorytree/ldaprecord

A fully-featured LDAP ORM.

5793.3M15](/packages/directorytree-ldaprecord)[cyrildewit/eloquent-viewable

Laravel package that allows you to associate views with Eloquent models

8851.1M6](/packages/cyrildewit-eloquent-viewable)[laracraft-tech/laravel-date-scopes

Some useful date scopes for your Laravel Eloquent models!

516231.8k3](/packages/laracraft-tech-laravel-date-scopes)[bolt/core

🧿 Bolt Core

582145.4k57](/packages/bolt-core)[esensi/model

The base model traits of Esensi

20067.0k1](/packages/esensi-model)[voryx/pgasync

Async Reactive Postgres Driver for PHP (Non-blocking)

11295.9k4](/packages/voryx-pgasync)

PHPackages © 2026

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