A micro framework for create a very simple decoupled ORM. This library intended to be very small and very simple to use;
Key Features:
These are the key components:
┌──────────────────────────┐
│ Repository │ ┌─────────────────────┐
│ │ ┌────│ Model │
│ │ │ └─────────────────────┘
│ ┌───────────────┴─────┐ │ │
│ │ Mapper │───┤ │
│ └───────────────┬─────┘ │ │
│ │ │ │ ┌─────────────────────┐
│ │ │ └────│ FieldMapping │
│ │ │ └─────────────────────┘
│ │ │
│ ┌───────────────┴─────┐
│ │ Query │
│ └───────────────┬─────┘
│ │
│ ┌───────────────┴─────┐
│ │ DbDriverInterface │───────────────┐
│ └───────────────┬─────┘ │
│ │ │
└──────────────────────────┘ .─────────.
│ │
│`─────────'│
│ │
│ DB │
│ │
│ │
`─────────'
For the examples below we will use the class ‘Users’;
<?php
class Users
{
public $id;
public $name;
public $createdate;
}
First of all will create a Table Mapping class:
<?php
// Creating the mapping
$mapper = new \ByJG\MicroOrm\Mapper(
Users::class, // The full qualified name of the class
'users', // The table that represents this entity
'id' // The primary key field
);
// Optionally you can define table mappings between the propoerties
// and the database fields;
// The example below will map the property 'createdate' to the database field 'created';
$mapper->addFieldMapping(FieldMap::create('createdate')->withFieldName('created'));
Then you need to create the dataset object and the repository:
<?php
$dataset = \ByJG\AnyDataset\Db\Factory::getDbRelationalInstance('mysql://user:password@server/schema');
$repository = new \ByJG\MicroOrm\Repository($dataset, $mapper);
Some examples with the repository:
<?php
// Get a single data from your ID
$users = $repository->get(10);
// Persist the entity into the database:
// Will INSERT if does not exists, and UPDATE if exists
$users->name = "New name";
$repository->save($users);
Get a collection using the query object:
<?php
$query = \ByJG\MicroOrm\Query::getInstance()
->table('users')
->fields(['id', 'name'])
->where('name like :part', ['part' => 'A%']);
// Will return a collection o 'Users'
$collection = $repository->getByQuery($query);
Returning multiples entities with a query:
<?php
$query = \ByJG\MicroOrm\Query::getInstance()
->table('order')
->join('item', 'order.id = item.orderid')
->where('name like :part', ['part' => 'A%']);
// Will return a collection of Orders and Items:
// $collection = [
// [ $order, $item ],
// [ $order, $item ],
// ...
// ];
$collection = $orderRepository->getByQuery(
$query,
[
$itemRepository->getMapper()
]
);
Field alias is an alternate name for a field. This is usefull for disambiguation on join and leftjoin queries. Imagine in the example above if both tables ITEM and ORDER have the same field called ‘ID’.
In that scenario, the value of ID will be overriden. The solution is use the FieldAlias like below:
<?php
// Create the Mapper and the proper fieldAlias
$orderMapper = new \ByJG\MicroOrm\Mapper(...);
$orderMapper->addFieldMapping(FieldMapping::create('id')->withFieldAlias('orderid'));
$itemMapper = new \ByJG\MicroOrm\Mapper(...);
$itemMapper->addFieldMappping(FieldMapping::create('id')->withFieldAlias('itemid'));
$query = \ByJG\MicroOrm\Query::getInstance()
->field('order.id', 'orderid')
->field('item.id', 'itemid')
/* Other fields here */
->table('order')
->join('item', 'order.id = item.orderid')
->where('name like :part', ['part' => 'A%']);
// Will return a collection of Orders and Items:
// $collection = [
// [ $order, $item ],
// [ $order, $item ],
// ...
// ];
$collection = $orderRepository->getByQuery(
$query,
[
$itemRepository->getMapper()
]
);
You can also add a MAPPER as a Field. In that case the MAPPER will create the field and the correct aliases.
<?php
$query = \ByJG\MicroOrm\Query::getInstance()
->fields([
$orderRepository->getMapper(),
$itemRepository->getMapper,
]);
<?php
// Creating the mapping
$mapper = new \ByJG\MicroOrm\Mapper(
Users::class, // The full qualified name of the class
'users', // The table that represents this entity
'id', // The primary key field
function () {
// calculate and return the unique ID
}
);
<?php
// Creating the mapping
$mapper = new \ByJG\MicroOrm\Mapper(...);
$fieldMap = FieldMap::create('propertyname') // The property name of the entity class
// The field name of the table. if not defined will use the property name.
->withFieldName('fieldname')
// The field alias of the field in the table. if not defined will use the field name.
->withFieldAlias('alias')
// Returns the pre-processed value before UPDATE/INSERT the $field name
// If the function returns NULL this field will not be included in the UPDATE/INSERT
->withUpdateFunction(function ($field, $instance) {
return $field;
})
// Returns the field value with a post-processed value of $field AFTER query from DB
->withSelectFunction(function ($field, $instance) {
return $field;
})
$mapper->addFieldMapping($fieldMap);
<?php
$recursive = \ByJG\MicroOrm\Recursive::getInstance('test')
->field('start', 1, 'start + 10')
->field('end', 120, "end - 10")
->where('start < 100')
;
$query = \ByJG\MicroOrm\Query::getInstance()
->withRecursive($recursive)
->fields(['start', 'end']);
/*
This will produce the following SQL:
WITH RECURSIVE test(start, end) AS (
SELECT 1 as start, 120 as end
UNION ALL SELECT start + 10, end - 10 FROM test WHERE start < 100
) SELECT start, end FROM test
*/
Defines the basic behavior for select and update fields;
If set in the update field map will make the field not updatable by the micro-orm. It is usefull for fields that are pre-defined like ‘Primary Key’; timestamp fields based on the update and the creation; and others
You can also set closure to be applied before insert or update a record. In this case will set in the Repository:
<?php
Repository::setBeforeInsert(function ($instance) {
return $instance;
});
Repository::setBeforeUpdate(function ($instance) {
return $instance;
});
It allows you to create a single database transaction with multiple repositories. If any of the repositories fails the transaction will be rolled back for all repositories. When you commit the transaction all repositories will be commited.
<?php
$repo1 = new Repository(...);
$repo2 = new Repository(...);
// Create the TransactionManager
$transactionManager = new TransactionManager();
$transactionManager->addRepository($repo1);
$transactionManager->addRepository($repo2);
// Start the transaction
$transactionManager->beginTransaction();
//
// Do some Repository operations with the repo;
// ...
// commit (or rollback all transactions)
$transactionManager->commitTransaction();
Just type:
composer require "byjg/micro-orm=4.0.*"
vendor/bin/phpunit