Object-Relational Behavioral Patterns

Sebastian Bergmann » 16 February 2009 » in New Features » 2 Comments

The Object_Freezer library that I introduced earlier here and here now supports all three object-relational behavioral patterns listed in Martin Fowler's "Patterns of Enterprise Application Architecture" book.

Unit of Work

Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.

This is achieved by automatically hashing objects in Object_Freezer::freeze(). Upon freezing, only dirty objects are written back to the object storage. An object is dirty if its hash has changed.

Identity Map

Ensures that each object gets loaded only once by keeping every loaded object in a map. Looks up objects using the map when referring to them.

This is achieved by caching previously fetched objects in Object_Freezer_Storage::fetch().

Lazy Load

An object that doesn't contain all of the data you need but knows how to get it.

This is achieved by (optionally) replacing aggregated objects in Object_Freezer_Storage::fetch() with objects of Object_Freezer_LazyProxy. A LazyProxy object provides explicit access to the real object through its getObject() method and implicit access through its implementations of __call(), __get(), and __set().

The question is: does the name Object-Relational Behavioral Patterns still fit when the objects are not mapped to a relational database but to a schema-free document-oriented database such as Apache CouchDB?

Defined tags for this entry: ,

Cool PHP Objects Sleep on the Couch

Sebastian Bergmann » 11 January 2009 » in New Features » 0 Comments

The Object_Freezer library for PHP provides the low-level functionality to store ("freeze") and fetch ("thaw") any PHP userland object to and from arbitrary object stores.

Today I added an object storage implementation that uses Apache CouchDB as its backend.

Apache CouchDB, the distributed, fault-tolerant and schema-free document-oriented database that provides scalability as a consequence of its design, is a natural fit for such an object store.

The following example shows how the Object_Freezer's new backend for CouchDB can be used to persist PHP objects:

<?php
require 'Object/Freezer/Storage/CouchDB.php';
 
class Foo
{
    public $a;
    protected $b;
    private $c;
 
    public function __construct($a, $b, $c)
    {
        $this->a = $a;
        $this->b = $b;
        $this->c = $c;
    }
}
 
$object = new Foo(1, 2, 3);
var_dump($object);
 
// Store the object in the database "test" of the
// CouchDB server that is running on localhost:5984.
$storage = new Object_Freezer_Storage_CouchDB('test');
$storage->store($object);
 
// Freezing the object added the "magic" attributes
// __php_object_freezer_uuid and __php_object_freezer_hash.
var_dump($object);
 
// Fetch the object (by ID) from the database.
var_dump($storage->fetch($object->__php_object_freezer_uuid));
?>

Below is the output produced by the script above:

object(Foo)#1 (3) {
  ["a"]=>
  int(1)
  ["b":protected]=>
  int(2)
  ["c":"Foo":private]=>
  int(3)
}

object(Foo)#1 (5) {
  ["a"]=>
  int(1)
  ["b":protected]=>
  int(2)
  ["c":"Foo":private]=>
  int(3)
  ["__php_object_freezer_uuid"]=>
  string(36) "8d17b95e-1410-4e54-a70c-064c09c79210"
  ["__php_object_freezer_hash"]=>
  string(40) "40cd89ec4ea3b5a1c1419c83b4ea643da5341ab8"
}

object(Foo)#10 (5) {
  ["a"]=>
  int(1)
  ["b":protected]=>
  int(2)
  ["c":"Foo":private]=>
  int(3)
  ["__php_object_freezer_uuid"]=>
  string(36) "8d17b95e-1410-4e54-a70c-064c09c79210"
  ["__php_object_freezer_hash"]=>
  string(40) "40cd89ec4ea3b5a1c1419c83b4ea643da5341ab8"
}

Here is an overview of the current feature set:

  • PHP objects, with the exception of objects of "special" classes such as Closure or PDO, can be frozen and thawed.
  • Graphs of objects, including those that contain circular references, are supported.
  • Frozen objects can be stored in and fetched from an Apache CouchDB database.
Defined tags for this entry: , ,