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

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

clintonnzedimma/sommy-orm
=========================

Sequelize-style lightweight ORM for PHP (Sommy ORM)

v1.0.0(8mo ago)21PHPPHP &gt;=8.0

Since Sep 7Pushed 3mo agoCompare

[ Source](https://github.com/clintonnzedimma/sommy-orm)[ Packagist](https://packagist.org/packages/clintonnzedimma/sommy-orm)[ RSS](/packages/clintonnzedimma-sommy-orm/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependenciesVersions (2)Used By (0)

Sommy ORM
=========

[](#sommy-orm)

Sommy ORM is a tiny, Sequelize‑style ORM for PHP built on PDO. It focuses on being simple and explicit: you define models with a schema, create tables via a query interface, and do straightforward CRUD without magic.

Works with MySQL, MariaDB, SQLite, and PostgreSQL.

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

[](#requirements)

- PHP &gt;= 8.0
- `ext-pdo` and the PDO driver for your database (e.g., `pdo_mysql`, `pdo_sqlite`, `pdo_pgsql`)

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

[](#installation)

Install via Composer (recommended):

```
composer require clintonnzedimma/sommy-orm
```

Or, if you are using this repository directly:

1. Install dependencies and dump autoload

```
composer install
composer dump-autoload
```

2. Require Composer autoloader from your app:

```
require __DIR__ . '/vendor/autoload.php';
```

Composer autoload is configured for `Sommy\ORM\` → `src/`.

Configuration
-------------

[](#configuration)

Create an array of connection settings and pass it to `Sommy\ORM\SommyManager`.

SQLite example:

```
use Sommy\ORM\SommyManager;

$sommy = new SommyManager([
    'dialect'  => 'sqlite',
    'database' => __DIR__ . '/database.sqlite',
]);
```

MySQL/MariaDB example:

```
$sommy = new SommyManager([
    'dialect'  => 'mysql', // or 'mariadb'
    'host'     => '127.0.0.1',
    'port'     => 3306,
    'database' => 'testdb',
    'username' => 'root',
    'password' => '',
    'charset'  => 'utf8mb4',
]);
```

### Connecting to MySQL

[](#connecting-to-mysql)

- Make sure the `pdo_mysql` extension is enabled (check with `php -m`).
- Ensure a MySQL server is running and you have database credentials.
- Create a database and user (example using the MySQL client):

```
mysql -u root -p
```

```
CREATE DATABASE testdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'secret';
GRANT ALL PRIVILEGES ON testdb.* TO 'appuser'@'localhost';
FLUSH PRIVILEGES;
```

- Configure Sommy to use MySQL (see example above), e.g.:

```
use Sommy\ORM\SommyManager;

$sommy = new SommyManager([
    'dialect'  => 'mysql',
    'host'     => '127.0.0.1',
    'port'     => 3306,
    'database' => 'testdb',
    'username' => 'appuser',
    'password' => 'secret',
    'charset'  => 'utf8mb4',
]);

// Optional: quick connectivity check
if (!$sommy->authenticate()) {
    throw new RuntimeException('MySQL connection failed');
}
```

PostgreSQL example:

```
$sommy = new SommyManager([
    'dialect'  => 'pgsql',
    'host'     => '127.0.0.1',
    'port'     => 5432,
    'database' => 'testdb',
    'username' => 'postgres',
    'password' => 'secret',
]);
```

Data Types
----------

[](#data-types)

Use the factory in `Sommy\ORM\DataTypes` to declare columns:

- INTEGER: `DataTypes::INTEGER([...options])`
- BIGINT, SMALLINT: `DataTypes::BIGINT()`, `DataTypes::SMALLINT()`
- STRING/VARCHAR: `DataTypes::STRING($length = 255, [...])`
- TEXT: `DataTypes::TEXT([...])`
- BOOLEAN: `DataTypes::BOOLEAN([...])`
- DATE, DATETIME, TIME, TIMESTAMP
- FLOAT, DECIMAL($precision = 10, $scale = 0)
- JSON (falls back to TEXT where unsupported)
- UUID (native on PostgreSQL, `CHAR(36)` elsewhere)

Common column options:

- `allowNull` (bool): allow NULL values (default: true)
- `default` (mixed): default value
- `unique` (bool): unique constraint (column-level)
- `primaryKey` (bool): marks column as primary key
- `autoIncrement` (bool): auto-increment (dialect‑aware)

Creating Tables
---------------

[](#creating-tables)

Use `QueryInterface` to create tables. Example `users` table:

```
use Sommy\ORM\DataTypes;

$qi = $sommy->getQueryInterface();
$qi->createTable('users', [
    'id'   => DataTypes::INTEGER(['primaryKey' => true, 'autoIncrement' => true, 'allowNull' => false]),
    'name' => DataTypes::STRING(255, ['allowNull' => false]),
    'age'  => DataTypes::INTEGER(),
    'is_admin' => DataTypes::BOOLEAN(['default' => false]),
    'created_at' => DataTypes::DATETIME(['allowNull' => false]),
], ['ifNotExists' => true]);
```

Drop a table:

```
$qi->dropTable('users', ['ifExists' => true]);
```

Defining Models
---------------

[](#defining-models)

Define a model with `SommyManager::define($name, $attributes, $options = [])`. This returns an instance of an anonymous subclass of `Model` that is bound to your table and schema.

```
use Sommy\ORM\Model;
use Sommy\ORM\DataTypes;

$User = $sommy->define('User', [
    'id'   => DataTypes::INTEGER(['primaryKey' => true, 'autoIncrement' => true, 'allowNull' => false]),
    'name' => DataTypes::STRING(255, ['allowNull' => false]),
    'age'  => DataTypes::INTEGER(),
], [
    'tableName' => 'users', // optional; defaults to strtolower('User')
]);
```

Important: Many `Model` methods are static (Sequelize‑like). You can:

- Call via the class name string of the returned instance:

```
$UserClass = $User::class; // get anonymous class name
$id = $UserClass::create(['name' => 'Alice', 'age' => 30]);
```

- Or create an instance and use instance helpers like `save()`:

```
$u = new $UserClass(['name' => 'Bob', 'age' => 25]);
$u->save(); // INSERT, sets primary key if available
```

For convenience, calling static methods on the instance (e.g., `$User->findAll()`) also works in practice, but using the class name string as shown above is clearer.

CRUD Examples
-------------

[](#crud-examples)

Create (static):

```
$UserClass = $User::class;
$id = $UserClass::create(['name' => 'Alice', 'age' => 30]);
```

Create + save (instance):

```
$u = new $UserClass(['name' => 'Bob']);
$u->age = 25;
$u->save(); // INSERT
```

Find:

```
$all = $UserClass::findAll();
$admins = $UserClass::findAll(['is_admin' => 1], ['order' => ['id' => 'DESC']]);
$first = $UserClass::findOne(['id' => 1]);
```

Update:

```
// Bulk update
$affected = $UserClass::update(['age' => 31], ['name' => 'Alice']);

// Instance update via save()
$alice = $UserClass::findOne(['name' => 'Alice']);
if ($alice) {
    $alice->age = 32;
    $alice->save();
}
```

Delete:

```
// Bulk delete
$deleted = $UserClass::destroy(['id' => [3,4,5]]); // IN (...) support

// Instance delete
$u = $UserClass::findOne(['id' => 2]);
if ($u) { $u->delete(); }
```

QueryInterface Reference
------------------------

[](#queryinterface-reference)

Available on `$sommy->getQueryInterface()`.

- select: `select(string $table, array $columns = ['*'], array $where = [], array $options = []) : array`
    - Where supports: `['col' => value, 'status' => ['a','b'], 'deleted_at' => null]`
    - Options: `order` (string or array), `limit` (int), `offset` (int)
- insert: `insert(string $table, array $data) : string|bool` (returns last insert id if available)
- update: `update(string $table, array $data, array $where) : int`
- delete: `delete(string $table, array $where) : int`
- createTable: `createTable(string $name, array $attributes, array $options = []) : bool`
- dropTable: `dropTable(string $name, array $options = []) : bool`

Identifier quoting and SQL types are dialect‑aware where it matters (e.g., MySQL backticks vs. PostgreSQL double quotes, SERIAL/BIGSERIAL, SQLite `INTEGER PRIMARY KEY`).

CLI: Migrations
---------------

[](#cli-migrations)

Sommy includes a tiny CLI in `bin/sommy` for simple time‑stamped migrations.

1. Initialize config (creates `sommy.config.php`):

```
php bin/sommy init:config
```

2. Create a migration file:

```
php bin/sommy migrate:create create_users
```

This generates `database/migrations/YYYMMDDHHMMSS_create_users.php` with a class like `Migration_YYYMMDDHHMMSS_create_users` containing `up()` and `down()`.

3. Edit your migration, e.g.:

```
use Sommy\ORM\QueryInterface;

class Migration_20250101010101_create_users
{
    public function up(QueryInterface $qi): void
    {
        $qi->createTable('users', [
            'id'   => ['type' => 'INTEGER', 'primaryKey' => true, 'autoIncrement' => true, 'allowNull' => false],
            'name' => ['type' => 'VARCHAR', 'length' => 255, 'allowNull' => false],
        ], ['ifNotExists' => true]);
    }

    public function down(QueryInterface $qi): void
    {
        $qi->dropTable('users', ['ifExists' => true]);
    }
}
```

4. Apply pending migrations:

```
php bin/sommy migrate:up
```

5. Revert last migration:

```
php bin/sommy migrate:down
```

The CLI records applied migrations in a table `sommy_migrations`.

Quick Start (End‑to‑End)
------------------------

[](#quick-start-endtoend)

```
require __DIR__ . '/vendor/autoload.php';

use Sommy\ORM\SommyManager;
use Sommy\ORM\DataTypes;

$sommy = new SommyManager([
    'dialect'  => 'sqlite',
    'database' => __DIR__ . '/database.sqlite',
]);

// Create a table (usually via migration)
$qi = $sommy->getQueryInterface();
$qi->createTable('users', [
    'id'   => DataTypes::INTEGER(['primaryKey' => true, 'autoIncrement' => true, 'allowNull' => false]),
    'name' => DataTypes::STRING(255, ['allowNull' => false]),
], ['ifNotExists' => true]);

// Define a model
$User = $sommy->define('User', [
    'id'   => DataTypes::INTEGER(['primaryKey' => true, 'autoIncrement' => true, 'allowNull' => false]),
    'name' => DataTypes::STRING(255, ['allowNull' => false]),
], ['tableName' => 'users']);

// Use the class name for static methods
$UserClass = $User::class;
$id = $UserClass::create(['name' => 'Alice']);

$all = $UserClass::findAll();
foreach ($all as $u) {
    echo $u->name . "\n";
}
```

Design Notes
------------

[](#design-notes)

- Minimal abstraction: generated SQL is straightforward and debug‑friendly.
- Dialect‑aware DDL: common types and primary/auto‑increment behaviors map correctly for MySQL/MariaDB, PostgreSQL, SQLite.
- Anonymous model classes: `define()` returns an instance; use `$Model::class` to access static methods cleanly.

Troubleshooting
---------------

[](#troubleshooting)

- Ensure the PDO driver for your DB is installed and enabled.
- For MySQL/MariaDB, set a valid `charset` (defaults to `utf8mb4`).
- If `migrate:up` fails, check your migration for typos in column definitions (e.g., `allowNull`, `primaryKey`).
- If a migration class fails to load or you see a PHP parse error, ensure method signatures include the parameter variable: use `public function up(Sommy\\ORM\\QueryInterface $qi): void` and `public function down(Sommy\\ORM\\QueryInterface $qi): void`.
- On MySQL/MariaDB, DDL statements (CREATE/DROP TABLE) auto-commit and may end a transaction. The CLI now guards commit/rollback, but if you saw "There is no active transaction", update to the latest version and re-run.

Model Generator
---------------

[](#model-generator)

Generate a model class (Laravel-style) into `database/models`:

```
php bin/sommy make:model User
```

Options:

- `--table=users`: set table name (default: lowercase name + 's')
- `-m` or `--migration`: also generate a migration stub (e.g., `create_users`)
- `--force`: overwrite the file if it exists

Autoload for dev:

- `composer.json` includes an `autoload-dev` mapping `Database\Models\` → `database/models/`.
- Run `composer dump-autoload` after generating models so Composer picks them up.

Using a generated model:

```
use Sommy\ORM\SommyManager;
use Database\Models\User;

$sommy = new SommyManager([...]);
User::register($sommy); // binds table + attributes defined in the model

// After defining attributes in User::register():
$id = User::create(['name' => 'Alice']);
```

###  Health Score

32

—

LowBetter than 72% of packages

Maintenance72

Regular maintenance activity

Popularity4

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity40

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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

Unknown

Total

1

Last Release

244d ago

### Community

Maintainers

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

---

Top Contributors

[![clintonnzedimma](https://avatars.githubusercontent.com/u/34009341?v=4)](https://github.com/clintonnzedimma "clintonnzedimma (7 commits)")

---

Tags

mysqlormorm-frameworkphppostgresqlsqlitesqlite3woskiphpormmysqlsqlitepostgresqlmariadbpdomigrations

### Embed Badge

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

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

###  Alternatives

[doctrine/dbal

Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.

9.7k578.4M5.6k](/packages/doctrine-dbal)[scienta/doctrine-json-functions

A set of extensions to Doctrine that add support for json query functions.

58523.9M35](/packages/scienta-doctrine-json-functions)[tommyknocker/pdo-database-class

Framework-agnostic PHP database library with unified API for MySQL, MariaDB, PostgreSQL, SQLite, MSSQL, and Oracle. Query Builder, caching, sharding, window functions, CTEs, JSON, migrations, ActiveRecord, CLI tools, AI-powered analysis. Zero external dependencies.

845.7k](/packages/tommyknocker-pdo-database-class)[voodoophp/voodorm

VoodOrm is a micro-ORM which functions as both a fluent select query API and a CRUD model class.

4910.5k1](/packages/voodoophp-voodorm)[ramadan/easy-model

A Laravel package for enjoyably managing database queries.

101.6k](/packages/ramadan-easy-model)

PHPackages © 2026

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