Every Inphusion object has meta data and private data. The meta data defines the object's unique identity, its position in the tree structure and a few other denormalised attributes to speed up common queries. Perhaps the most important metadata attribute is the object's class. This attribute defines which part of Inphusion will handle requests concerning the object. In fact, when I started Inphusion, I didn't really understand object orientation at all, and I called the classes "datatypes" and their definitions "handlers." It's still a reasonable way to think about what's happening.
Here's some of the basic metadata attributes, just to get us started:
What kind of Private Data a class has is defined by the handler. So all objects have the same list of Meta-Data attributes, but can do whatever they like when it comes to Private Data. The class knows where its own Private Data is stored and how to access it. Each class provides a "prvRead" and a "prvSave" method to expose these abilities. The equivalent public methods, "pubRead" and "pubSave" are defined in the base object class. These methods iterate through all of the prvRead / prvSave methods in the classes which make up the object.Example
Imagine that Object 15643 is of class Manager. That class inherits from class Person which in turn inherits from the object prototype class. Each class stores its own private data in its own database table:
A factory class handles object creation. It dynamically loads all the classes to instantiate an object as they are needed. Once all the class files are loaded, it can instantiate the object. A workaround for PHP's current lack of chained constructors is implemented, so initiation tasks can be carried out per-class if necessary.
So, at this level, Inphusion is providing an object/relational mapping layer. The application developer doesn't need to know which tables are storing the data - they just call pubRead and pubSave (or one of a number of other methods). These are defined in CObject_Proto, and their basic algorithm is to iterate through all the relevant private methods defined in the other classes which make up the object.The Query Proxy
Since an object might be stored in n tables, it follows that n queries would be required to handle it in the database, right? Wrong. Inphusion includes a Query Proxy which aggregates query sections from each of the private methods into as few queries as possible, examining changes made against the currently-recorded copy of the object. This means that although a brand new INSERT will still require n queries, most other operations will be 'cheaper'. SELECT queries are dynamically compiled so that a single query joins each required table to return the requested data. Obviously if an object is spread very "thinly" accross several classes, performance will degrade, so it makes sense in that situation to refactor the object as a single class.Native and Non-native Classes
Although I've done my best to keep private terminology to an absolute minimum, a little bit of jargon is unavoidable, so...
Objects which inherit directly from CObject_Proto are called primitive classes and those which are at the end of a line of inheritance from three classes or more are called distant classes. All objects defined in PHP are referred to as Native classes... and that statement implies the possibility of non-native classes... These don't actually exist in code just yet, but they will very soon...
Non-native classes are defined outside of the framework itself, by the users of an application built with it. So a user (without any development) can create, at run-time, very specific subclasses of a native class. For example, consider a (native) "memo" class which defines just a single text attribute, "strMemoText". The user could "subclass" this and create a (non-native) "Telephone Message Memo" class. Their new class could define two new attributes, "strWhoCalledYou" and "dtmTimeWhenTheyCalled". Data held in non-native definitions gets collapsed into a single field in the Persistent Store, so they are inefficient... but if a non-native class is very frequently used, it should be re-written as a native one!Object Introspection
An application can request a list of public methods exposed by an object. It can then call any of these methods at will. The basic object prototype (CObject_Proto) defines a set of methods for displaying and handling forms to create and edit objects etc., drawing from the inheriting class definitions for complex objects. An application could use or extend these, or ignore them altogether and provide its own functionality if desired.
In a typical situation, the application would ask the object to display an "edit object" form ( $objMyObject->pubShowEditForm(); ) and this would iterate through the inherited classes, building the form piecemeal from private methods defined in each class, and finally showing the form to the user. If necessary, the final class definition can override pubShowEditForm and provide a completely custom form. At the other end of the axis, if the inherited classes don't provide any form information, then the base object can generate a form based purely on what it knows of it's own attributes - think M$ Access "autoform" functionality.
Object Workflow is provided by manipulating the "status" meta data attribute and the object's position in the data hierarchy. These are not altered directly, but through methods exposed by each class in a very similar way to that which I've just described.
$intIDofDemoObject = 15643;
$objMyDemoObject = CFactory:: InstantiateObjectWhichAlreadyExists($intIDofDemoObject)
$objMyDemoObject -> pubRead(); //Read the details of the object from the Persistent Store into the object instance
echo $objMyDemoObject->vchDepartment; //Returns, for example, "Marketing"
$arrMethods = $objMyDemoObject->pubListPublicMethods(); //Returns a list of Methods the class exposes to the application
//Lucky Mr Manager! This method might fire off a memo to Accounts, send a confirmation letter, whatever...
//Note that you could give a pay rise to any subclass of "Person" so the method is defined in the Person class, not the Manager.
$objMyDemoObject->pubSave(); //Write the details of the object back into the Persistent Store