PicoMapper is a minimalist data mapper built on PicoDb.
- Built on PicoDb
- No configuration files
- License: MIT
- PHP >= 7.3
- PDO extension
- Sqlite, Mssql, Mysql or Postgresql
composer require tithely/picomapper
use PicoDb\Database;
use PicoMapper\Mapper;
use PicoMapper\Definition;
$db = new Database([...]);
$mapper = new Mapper($db);
In order to map to or from the database, a mapping must be built from a definition. A definition consists of a table, a primary key (one or more columns that uniquely identifies a record), columns, children (other definitions) and special options that control things like what is considered a deleted record.
Consider a blog system with posts, comments and authors. A post has one author and many comments, a comment has one author. Assuming posts, comments and authors have their own tables, a suitable definition would look like the following:
$author = (new Definition('authors'))
->withColumns('name')
->withDeletionTimestamp('deleted');
$comment = (new Definition('comments'))
->withColumns('content')
->withOne($author, 'author', 'id', 'author_id')
->withDeletionTimestamp('deleted');
$post = (new Definition('posts'))
->withColumns('title', 'content')
->withOne($author, 'author', 'id', 'author_id')
->withMany($comment, 'comments', 'post_id')
->withDeletionTimestamp('deleted');
$mapping = $mapper->mapping($post);
The second constructor argument for Definition
is an array of columns that uniquely identify a record within the table.
By default it's ['id']
.
Data to be set on insert and update can be set by calling withCreationData()
and withModificationData()
respectively. For example if you wanted to add a date_entered
and date_modified
columns to the $post
definition, you would enter it as follows:
$post = (new Definition('posts'))
->withColumns('title', 'content')
->withOne($author, 'author', 'id', 'author_id')
->withMany($comment, 'comments', 'post_id')
->withCreationData(['date_entered' => gmdate('Y-m-d G:i:s')])
->withModificationData(['date_modified' => gmdate('Y-m-d G:i:s')]);
->withDeletionTimestamp('deleted');
Mappings have the same interface as PicoDb's Table
class. That is, you can chain conditions and call findOne()
or
findAll()
to fetch records or insert()
, update()
, remove()
and save()
to modify records. In all cases, the
definition will be used to intelligently return or accept a structured array.
In the example above you could fetch or save a post using the following structured array, and all table relationships will be followed automatically.
$post = [
'id' => 'abc123',
'author' => [
'id' => 'zxy321',
'name' => 'John Doe'
],
'title' => 'Data Mappers Rock',
'content' => 'They save you time',
'comments' => [
[
'id' => 'def456',
'post_id' => 'abc123',
'author' => [
'id' => 'zxy321',
'name' => 'John Doe'
],
'content' => 'Did you like my post?'
],
[
'id' => 'hij789',
'post_id' => 'abc123',
'author' => [
'id' => 'klm012',
'name' => 'Jane Doe'
],
'content' => 'Nice article!'
],
]
];
$mapper->save($post);
$saved = $mapper->eq('id', 'abc123')->findOne();
// $saved will be identical in structure to post
Hooks are callbacks that can be triggered when a mapping performs the successful insert, update or removal of a record. A hook registered against a mapper will be used for all top level mappings it creates.
$mapper->registerHook('updated', function ($table, $key, $updated, $original) {
printf('Table %s (ID: %s) was updated...', $table, implode(':', $key));
});