-
Notifications
You must be signed in to change notification settings - Fork 0
Defining Models
A model is a subclass of InitORM\ORM\Model. Configuration is declarative: you set protected properties on the class, and the model constructor wires up everything else. Every property is optional with sensible defaults.
| Property | Type | Default | What it does |
|---|---|---|---|
$schema |
string |
(derived) | Table name. Auto-derived from class short name when unset. |
$schemaId |
string |
'id' |
PK column. Lifted out of update()'s $set into a WHERE; used by save(). |
$entity |
class-string |
Entity::class |
Class used to hydrate read() rows via PDO::FETCH_CLASS. |
$credentials |
array|null |
null |
Standalone connection credentials. Null → shared DB facade. |
$writable |
bool |
true |
False blocks create() / createBatch() with WritableException. |
$readable |
bool |
true |
False blocks read() with ReadableException. |
$updatable |
bool |
true |
False blocks update() / updateBatch() with UpdatableException. |
$deletable |
bool |
true |
False blocks delete() with DeletableException. |
$createdField |
string|null |
null |
Auto-filled with date($timestampFormat) on every create. Disabled when null. |
$updatedField |
string|null |
null |
Auto-filled with date($timestampFormat) on every update. Disabled when null. |
$useSoftDeletes |
bool |
false |
True → delete() sets $deletedField instead of issuing DELETE. |
$deletedField |
string|null |
null |
Required when $useSoftDeletes is true. Soft-delete marker column. |
$timestampFormat |
string |
'Y-m-d H:i:s' |
date() format used for all three timestamp columns. |
class Posts extends \InitORM\ORM\Model
{
protected string $schema = 'posts';
}If you omit $schema, the constructor derives it from the class short name using snake_case conversion:
class PostCategory extends \InitORM\ORM\Model {}
(new PostCategory())->getSchema(); // 'post_category'Conversion rules:
| Class short name | Derived schema |
|---|---|
Posts |
posts |
Post |
post |
PostCategory |
post_category |
PostCategoryTag |
post_category_tag |
XMLParser |
xml_parser |
HTTPRequest |
http_request |
User2Login |
user2_login |
For anything more exotic (pluralisation, table prefixes, multi-tenancy), set $schema explicitly.
class Posts extends \InitORM\ORM\Model
{
protected string $schema = 'posts';
protected string $schemaId = 'id'; // default
}Two methods use it:
-
update()lifts the PK out of$setinto a WHERE — so you never accidentally try to write the PK:$posts->update(['id' => 5, 'title' => 'X']); // UPDATE posts SET title = :title WHERE id = :id
-
save(Entity)checks the PK to decide betweencreate()andupdate():$entity = new PostEntity(['title' => 'New']); $posts->save($entity); // → create() $entity = new PostEntity(['id' => 1, 'title' => 'Edit']); $posts->save($entity); // → update()
For non-id keys, set $schemaId explicitly:
class Sessions extends \InitORM\ORM\Model
{
protected string $schema = 'sessions';
protected string $schemaId = 'session_id';
}class Posts extends \InitORM\ORM\Model
{
protected string $schema = 'posts';
protected string $entity = \App\Entity\PostEntity::class;
}read() hands the SELECT statement to the DataMapper with asClass($this->entity). Subsequent fetches return instances of that class. The default is the bare Entity — perfectly usable for projects that don't need accessor / mutator hooks.
The class must accept a no-argument constructor (or have a ?array $data = [] parameter, which Entity does). See Entities.
class ReportsEvents extends \InitORM\ORM\Model
{
protected string $schema = 'events';
protected ?array $credentials = [
'driver' => 'pgsql',
'host' => 'reports.internal',
'database' => 'reports',
'username' => 'reports_ro',
'password' => '…',
];
}When $credentials is non-null, the constructor calls DB::connect($credentials) to build a fresh Database. This bypasses the shared facade. See Multiple Connections.
When $credentials is null (default), the constructor calls DB::getDatabase() — which throws if no DB::createImmutable() has been done yet.
class Configuration extends \InitORM\ORM\Model
{
protected string $schema = 'configuration';
protected bool $writable = false;
protected bool $updatable = false;
protected bool $deletable = false;
}
(new Configuration())->read()->rows(); // OK
(new Configuration())->create([...]); // WritableExceptionEach flag is checked at the very top of the corresponding method — before any SQL is built or sent. See Permission Gates for the full pattern.
class Posts extends \InitORM\ORM\Model
{
protected string $schema = 'posts';
protected ?string $createdField = 'created_at';
protected ?string $updatedField = 'updated_at';
protected bool $useSoftDeletes = true;
protected ?string $deletedField = 'deleted_at';
protected string $timestampFormat = 'Y-m-d H:i:s'; // default
}See Timestamps and Soft Deletes for the details — including the soft-delete invariant validation that fires at construction.
__construct() runs three steps in order:
-
Auto-derive
$schemaif it was not set on the subclass. -
Validate the soft-delete invariant —
$useSoftDeletes = truewithout a$deletedFieldraisesModelException. -
Acquire the Database —
DB::getDatabase()orDB::connect($credentials).
Subclasses overriding __construct should set their properties before calling parent::__construct():
class Posts extends \InitORM\ORM\Model
{
public function __construct(string $schema = 'posts')
{
$this->schema = $schema;
parent::__construct(); // ← lifecycle runs here
}
}That said — overriding the constructor is rare. The conventional path is to declare properties directly on the class so PSR-4 autoloading composes cleanly with new MyModel().
A multi-tenant Documents model that:
- Uses a custom table name.
- Has a non-
idprimary key. - Hydrates as a custom entity.
- Auto-fills timestamps.
- Supports soft delete.
- Connects to a tenant-specific database (via
$credentialsthat come from the parent class).
namespace App\Model;
use InitORM\ORM\Model;
abstract class TenantModel extends Model
{
public function __construct(string $tenantHost)
{
$this->credentials = [
'driver' => 'mysql',
'host' => $tenantHost,
'database' => 'tenant_app',
'username' => 'app',
'password' => '…',
];
parent::__construct();
}
}
class Documents extends TenantModel
{
protected string $schema = 'documents';
protected string $schemaId = 'doc_id';
protected string $entity = \App\Entity\DocumentEntity::class;
protected ?string $createdField = 'created_at';
protected ?string $updatedField = 'updated_at';
protected bool $useSoftDeletes = true;
protected ?string $deletedField = 'deleted_at';
}
$docs = new Documents('tenant-a.db.internal');
$docs->create(['title' => 'Onboarding']);-
Entities — building the
$entityclass. - CRUD Operations — what each CRUD method does, in detail.
- Timestamps — how auto-fill behaves at the boundary.
-
Multiple Connections —
$credentials, facade, secondary connections.
InitORM ORM · MIT · maintained by Muhammet ŞAFAK · part of the InitORM stack
Getting Started
Models
Entities
Cross-Cutting
Reference
Upgrading
Project