måndag 2 januari 2012

Introducing Simplx Mirage part III

So, in the last post i tried to demystify the inner workings of Mirage a bit. Now its time for some practical stuff again, namely, relationships between objects.

A word on associations
As you might be aware, a cornerstone of Object Oriented programming (well actually in systematics as a whole) is the ability to be able to describe one objects relationships to its own parts, and also associations to other objects in its vicinity which affects its daily activity.
The most important types of associations can be categorized as being:

- Composite (is part of)
- Aggregate (uses)
- Reference (knows of)

An association is to be considered a Composite when one of the related Objects can not function in a context other than that in which it was created. Examples of such associations are:

- Pages in a book. Any Object could reference a book page, however a single page would make little sense outside the book which it is originally a part of. Also, an individual book page could not be in two books at the same time.

Aggregates are more flexible in nature as they allow dynamic relationships between more Objects than one. These are what you resort to when you find that a so called one-to-many relationship is called for. Examples of such are:

- Books in a shelf. A book will probably be moved from shelf to shelf during its life span. Even though it may end up in strange company from time to time, it will still be perfectly readable never the less. Not only can the book be moved, it can also be associated with one or more owners.

Reference is the association type with least dependency level. It is as its name suggests simply a named reference to an entity and is likely to be registered only at one end. The referenced Object will probably not be aware of the relationship.

- A reference in a book to another book or author.

So, summing it up, Composite relationships are really rigid and pretty reliable. Aggregates are much more dynamic and needs more explicit rules to govern them. Such as a penalty system for people who don't return your books to their correct shelf ;) And references are what helps is build simple, often pretty loose, networks of relationships between data.

So far Mirage handles Composite and Aggregate associations.

Keeping it conventional
Associations in Mirage are represented and managed in a simple and highly conventional manner. MODX actually, as do most file systems, handle these two types of relationships out of the box.

In an hierarchical file system structure any resource which is located in a folder is considered a Composite. As a direct consequence of this the resource will be deleted it its parent folder is deleted.

And then we have the Aggregates. In the world of Unix, Linux and Windows 7, and MODX, you have the concept of Symlinks. A Symlink, or symbolic link, makes it possible to create a link to an external entity enabling you to interact with it as if it was part of your local structure. If the object which contained the Symlink was deleted, the actual entity to which the link pointed will remain, unaffected.

Simplx Mirage uses the exact same metaphore to build hierarchical object relationships. Look at the following example:

$myObject = MyClass->getObject(10);
$myNewAggr = $myObject->addAggregate(22); // lets assume the Class is named 'SomeAggrClass'
$myNewComp = $myObject->addComposite('SomeCompClass');

The code above would result in the modResource with id 10 getting 2 child resources:

- The first would be a Symlink to an existing modResource with the id 22.

- The second resource to show up as a child to modResource 10 is a document using the 'SomeCompClass' template.

Simple right? Lets add some type check etc.

Order please!
If order was of limited concern to us we could stick with the above code. In my world of order and quest for readability l would want my associated objects to end up in a logical sub-structure. As is, the child resources are added in a jumble under their parent. This is of no concern to Mirage but to a system user or admin it would ruin usability.

Simplx Mirage has a nice little configuration API which i will write more about in a later post. Today I will cover the Simplx_Mirage_Object->_useFoldersForAssoc  boolean flag.

Simplx_Mirage_Object->_useFoldersForAssoc tells Mirage to store associated objects in folders which by default will use the same naming as the object type they represent. The above code would in other words expect a folder structure like this:

MyClass (folder)
- SomeAggrClass (folder)
- SomeCompClass (folder)

if _useFoldersForAssoc is set to true. If the expected structure is missing you will get an exception.

This brings me to the most important practice:

- Always wrap addAggregate, addComposite and their get and delete friends in more specialized Class members. Look at the following code and you will get the big point of this:

class BirthdayParty extends Simplx_Mirage_Object {
  public function __construct($id){
    $this->_useFoldersForAssoc = true;
    parent::__construct($id);
  }

  public function addInvitation($to, $answerBy){ 
    $invite = $this->addComposite('Invitation');
    $invite->to = $to;
    $invite->answerBy = $answerBy;
    $invite->save();
  }

public function getInvitations(){ 
  .....
  }
}

That's it for now folks
Gotta run! Have a bus to catch :)
Leave comments if you have questions!