jpi / orm
Simple & lightweight ORM
Installs: 1 085
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 6
pkg:composer/jpi/orm
Requires
- php: ^8.0
- jpi/database: ^2.0
- jpi/query: ^2.2.2
- jpi/utils: ^1.0
Requires (Dev)
- jpi/codestyles: ^1.0.1
- 2.x-dev
- v2.4.2
- v2.4.1
- v2.4.0
- v2.3.0
- v2.2.12
- v2.2.11
- v2.2.10
- v2.2.9
- v2.2.8
- v2.2.7
- v2.2.6
- v2.2.5
- v2.2.4
- v2.2.3
- v2.2.2
- v2.2.1
- v2.2.0
- v2.1.1
- v2.1.0
- v2.0.3
- v2.0.2
- v2.0.1
- v2.0.0
- v2.0.0-beta.2
- v2.0.0-beta.1
- v1.1.3
- v1.1.2
- v1.1.1
- v1.1.0
- v1.0.2
- v1.0.1
- v1.0.0
- dev-copilot/support-eager-loading-entities
- dev-copilot/add-unit-tests-setup
- dev-array-collection
- dev-copilot/sub-pr-46
- dev-belongs-to-reload
- dev-entity-clone
- dev-copilot/kill-depth-concept
This package is auto-updated.
Last update: 2026-01-10 23:10:03 UTC
README
A super simple & lightweight ORM following the active record pattern.
This has been kept very simple stupid (KISS), with minimal validation (PHP type errors only) to reduce complexity in the library and maximize performance for consumer developers. Therefore, please make sure to add your own validation if using user inputs in any database queries.
Features
- Easy to configure for your project's entities
- Supporting scalar types, array, and date/time and relationships
Many-to-One,One-to-ManyandOne-to-One - Fluent, chainable API for CRUD operations, using integrated query builder from jpi/query
Dependencies
- PHP 8.0+
- Composer
- PHP PDO
- MySQL 5+
- jpi/database v2
- jpi/query v2
Installation
Use Composer
$ composer require jpi/orm
Properties and Methods for Setup
You will need to extend \JPI\ORM\Entity and then define the following:
getDatabase(): \JPI\Database
This method must be implemented to provide the database connection for this entity. \JPI\Database is just an extension of PDO - you can find out more here.
$table: string
The database table name for this entity.
$dataMapping: array
This array defines the structure of your entity and maps to your database columns. Each key is a column name and the value is an array with:
type(required): One of:string,int,float,array,date,date_time,belongs_to,has_one,has_manydefault_valueseparator: The separator forarraytype columns when stored as delimited strings (defaults to",")entity: The related entity class name (required for relationship types)column- The database column behind this for
belongs_totype (defaults to{key}_id) - The key in related entity for
has_many&has_onetypes that links back to this
- The database column behind this for
cascade_delete: Whether to delete related entities when this entity is deleted (forhas_oneandhas_manytypes)cascade_clone: Whether to clone related entities when this entity is cloned viaclone- essentially creates new records with same data, else it sets to null/empty (forhas_oneandhas_manytypes)
protected static array $dataMapping = [ "name" => [ "type" => "string", ], "sku" => [ "type" => "string", ], "price" => [ "type" => "float", "default_value" => 0.00, ], "categories" => [ "type" => "array", "separator" => ",", // Optional, defaults to "," ], "created_at" => [ "type" => "date_time", ], ];
$columnPrefix: string - optional
Some database designers like to prefix their table columns. For example, the products table might have columns like product_id & product_name instead of id & name. Set this property to add that prefix automatically.
Note: the first underscore is required.
$defaultOrderByColumn: string - optional
The default column to order results by when selecting records and haven't specified an order. Default is id.
$defaultOrderByASC: bool - optional
Whether the default ordering should be ascending. Default is true.
Complete Example
... class Product extends \JPI\ORM\Entity { protected static string $table = "products"; protected static array $dataMapping = [ "name" => [ "type" => "string", ], "sku" => [ "type" => "string", ], "price" => [ "type" => "float", ], "stock" => [ "type" => "int", ], "created_at" => [ "type" => "date_time", ], ]; public static function getDatabase(): \JPI\Database { return new \JPI\Database("mysql:host=localhost;dbname=shop", "username", "password"); } ... }
Usage
Retrieving Entities
getById(int $id): ?static - Get an entity by its ID.
newQuery(): QueryBuilder - Get a query builder instance for advanced queries. See Query Builder section for examples.
Accessing Entity Data
You can get and set entity values using simple property access, these are the keys from $dataMapping. When setting the value must be value for the type defined or null.
Creating and Saving Entities
factory(?array $data = null): static - Create a new entity instance, and optionally set initial data in one call.
insert(array $data): static - Create and save an entity in one call.
save(): bool - Save (insert or update) the entity to the database.
Deleting Entities
delete(): bool - Delete the entity from the database.
Utility Methods
isLoaded(): bool - Check if the entity has been loaded from or saved to the database.
isDeleted(): bool - Check if the entity has been deleted.
toArray(): array - Convert the entity to an array.
reload(): void - Reload the entity from the database.
Query Builder
The query builder (accessed via newQuery()) provides a fluent interface for building database queries. It uses \JPI\Database\Query\Builder from jpi/query, see documentation there for full details on available query methods.
Relationships
The ORM supports three types of relationships:
belongs_to - Many-to-One
class Order extends Entity { ... protected static array $dataMapping = [ ... "customer" => [ "type" => "belongs_to", "entity" => Customer::class, "column" => "customer", // Defaults to "customer_id" if not specified ], ... ]; ... } $order = Order::getById(1); $customer = $order->customer; // Lazy loads the Customer entity
has_many - One-to-Many
class Order extends Entity { ... protected static array $dataMapping = [ ... "items" => [ "type" => "has_many", "entity" => OrderItem::class, "column" => "order", // The key in OrderItem that links back "cascade_delete" => true, ], ... ]; ... } $order = Order::getById(1); $items = $order->items; // Lazy loads a Collection of OrderItem entities
has_one - One-to-One
class Order extends Entity { ... protected static array $dataMapping = [ ... "payment" => [ "type" => "has_one", "entity" => Payment::class, "column" => "order", "cascade_delete" => true, ], ... ]; ... } $order = Order::getById(1); $payment = $order->payment; // Lazy loads the Payment entity
Support
If you found this library interesting or useful please spread the word about this library: share on your socials, star on GitHub, etc.
If you find any issues or have any feature requests, you can open a issue or email me @ jahidulpabelislam.com 😏.
Authors
Licence
This module is licensed under the General Public Licence - see the licence file for details.