Sledgehammer ORM module: Object relational mapping

22.07.0 2022-08-07 08:15 UTC

README

The Object-relational mapping (ORM) module for the Sledgehammer Framework.

Features

  • Full AutoCompletion support
  • POCO support. The Repository can load Plain Old Class Objects (POCO's)
  • Detect relations from the database
  • An optional ActiveRecord frontend
  • Linq style filtering support
  • Support for complex property mapping. A column "city" can be mapped to property "address->city"
  • 1 database record maps to only 1 instance. via an IdentityMap
  • Relations are objects, To set the "customer_id" you'll set the "customer" property to a customer object.
  • Cascading save(). A save will update & insert all connected records.
  • Support for multiple backends: PDO (MySQL, SQLite), Webservices (Twitter, etc)
  • Clean queries. (No "1 = 1" where statements, etc)

Usage

use Sledgehammer\Orm\Repository;
// inside your bootstrap.php
$repo = Repository::instance();
$repo->registerBackend(new DatabaseRepositoryBackend("default")); // Extract models from the "default" database connection.

// Somewhere in your application
$repo = Repository::instance();
$customer = $repo->getCustomer($_GET['id']);
$customer->name = $_POST['name'];
$repo->saveCustomer($customer);

// When the Customer class extends Sledgehammer\ActiveRecord the familiar API is also available
$customer = Customer::one($_GET['id']);
$customer->name = $_POST['name'];
$customer->save();

// Linq style filtering
$selection = $repo->allCustomers()->where(array('name' => 'James Bond'))->where(function ($c) { return $c->isSpecialAgent(); });
$list = Customer::all()->select('name', 'id'); // Results in: array($id1 => $name1, $id2 => $name2, ...)

Relations and Placeholders

The relations of objects are loaded on demand via placeholder classes. Just use the object as if all the relations are already loaded:

$customer->orders[0]->product->title;

Works and provides autocompletion all the way.

A downside to the placeholder technique is that:

if ($customer->orders[0]->id === $order->id) { ... } // Always works

if ($customer->orders[0] === $order) { ...} // WRONG. Doesn't work reliably

This is because $order might still be a BelongsToHolder object that will be replaced when used (calling a function, getting or setting a property) Sidenote: A BelongsToHolder often knows the id value and reading $order->id won't trigger a replacement/query.

Update a relation

You wont find any "customer_id" properties in the objects, to change the "customer_id" you'll need to use a customer object.

$order->customer = $repo->getCustomer(1);
$repo->saveOrder($order);

Don't do this

$order->customer->id = 1; // WRONG
$repo->saveOrder($order);  // Throws Exception

This is because you're changing the customer object which the repository tries to save before the order and id changes aren't allowed.

Dictionary

Backend: A data retrieval and storing mechanism. Model: A configuration to map backend data to instances. Instance: An object that is created by the Repository from backend data based on a Model.