Skip to content
comhon-project edited this page Aug 13, 2017 · 58 revisions

Table of contents

  1. Object Collection
    1. Main Object Collection
  2. Object serialization
  3. Object deserialization
  4. Object interfacing
    1. import
      1. Foreign properties import
    2. Export
      1. Foreign properties export
    3. Interfacing preferences
      1. privateContext
  5. Date time management
    1. Import and export
    2. Database time zone

Object Collection

An Object Collection permit to store objects and find them in constant time. Objects are grouped by model and by id. Obviously an object without id property cannot be stored in Object Collection.

Example of an Object Collection structure :

[
    person : [
        an_id_one : person_object_one,
        an_id_two : person_object_two
    ],
    town : [
        an_id_one : town_object_one
    ],
    house : [
        an_id_one : house_object_one,
        an_id_two : house_object_two
    ]
]

Example of usage :

$lPersonOne; // consider object already exists, has a model Person and has an id 'one'

$objectCollection = new OjectCollection();
$objectCollection->addObject($lPersonOne);

$objectCollection->hasObject('one', 'Person');           // return true
$object = $objectCollection->getObject('one', 'Person'); // return object previously added

$objectCollection->hasObject('two', 'Person');           // return false
$object = $objectCollection->getObject('two', 'Person'); // return null

$objectCollection->hasObject('one', 'House');            // return false
$object = $objectCollection->getObject('one', 'House');  // return null

Main Object Collection

MainObjectCollection is a singleton that store all deserialized (loaded) and imported objects. This singleton is usefull to know which object already exists and avoid redundants deserializations.

$object = MainObjectCollection::getInstance()->getObject('an_id', 'a_model_name');

Object serialization

Whatever is your serialzation you just have to call one function save() to serialize your object. Obviously the model associated to your object must have a serialization.

$object->save();

Specific case for sql database

Your table has an incremental id

Like other serializations call save() function but there are two cases to identify :

  1. if your Object doesn't have id set, an INSERT will be executed. if INSERT is successfull, id will be set in your object.
  2. if Object has id set, an UPDATE will be executed

Your table doesn't have an incremental id

you must specify your operation (insert or update)

$object->save(SqlTable::INSERT);
$object->save(SqlTable::UPDATE);

Object deserialization

Whatever is your serialzation you just have to call one function loadObject() to deserialize your object. Obviously the model associated to your object must have a serialization. When you load an object this object is stored in MainObjectCollection.

$object = $modelOne->loadObject('12');

// if your model has several id properties you must specify them in a json encoded array 
// order of values must be the same as order of id properties in manifest
$object = $modelTwo->loadObject('[1,1501774389]');

Thanks to MainObjectCollection if an object has already been loaded it will not be loaded again (except if you force it).

// load object
$object = $modelOne->loadObject('12');

// return same instance object retrieve from MainObjectCollection
$object = $modelOne->loadObject('12');

// like previous instruction but force to call deserialization 
// and merge current object instance with serialized object
$object = $modelOne->loadObject('12', true);

Object interfacing

Interfacing consist to import entry in specific format to populate a comhon object or conversely export comhon object to specific format. Comhon! provide three interfacer :

interfacer handled format handled parsed format
StdObjectInterfacer JSON stdClass
AssocArrayInterfacer JSON array
XMLInterfacer XML DOMElement

All interfacers extends Interfacer so they are very similar and have the same management. We will give example with a random interfacer but keep in mind that every examples are possible with all interfacers.

import

$model = ModelManager::getInstance()->getInstanceModel('person');
$stdOject = json_decode('{"id":1,"firstName":"John"}');

$stdInterfacer = new StdObjectInterfacer();

// via interfacer
$importedPerson = $stdInterfacer->import($stdOject, $model); // return instance of ComhonObject
echo $importedPerson->getValue('firstName'); // output 'John'

// via model
$importedPerson = $model->import($stdOject, $stdInterfacer); // return instance of ComhonObject
echo $importedPerson->getValue('firstName'); // output 'John'

// via comhon object
$person = new Object($model);
$person->setValue('lastName', 'Doe');
$person->fill($stdOject, $stdInterfacer); // fill current instance of ComhonObject
echo $person->getValue('firstName'); // output 'John'
echo $person->getValue('lastName'); // output 'Doe'

Foreign properties import

When a value corresponding to a foreign property is imported it's only an id. Import will automaticaly try to find if referenced object exists in Main Object Collection and get this instance otherwise it will create a new object.

$model = ModelManager::getInstance()->getInstanceModel('person');
$stdOject = json_decode('{"id":1,"firstName":"John","lastName":"Doe","mother":2,"children":[3,4]}');

$woman = new Object($model);
$woman->setValue('id', 2);
$woman->setValue('firstName', 'Jane');
$woman->setValue('lastName', 'Doe');

$stdInterfacer = new StdObjectInterfacer();

$importedPerson = $stdInterfacer->import($stdOject, $model); // return instance of ComhonObject
echo $importedPerson->getValue('children')->getValue(1)->getValue('id');
// output 4
echo $importedPerson->getValue('mother')->getValue('firstName');
// output 'Jane'
echo $woman === $importedPerson->getValue('mother') ? 'same instance' : 'different instance';
// output 'same instance'

export

$model; // we take model previously instanciated in import
$person; // we take person previously set in import

$XMLInterfacer = new XMLInterfacer();

// via interfacer
$exportedStdObject = $XMLInterfacer->export($person); // return instance of DOMNode

// via comhon object
$exportedStdObject = $person->export($XMLInterfacer); // return instance of DOMNode

// via model (be careful when you use this method, $model and $person model must match)
$exportedStdObject = $model->export($person, $XMLInterfacer); // return instance of DOMNode

// stringify exported object
$xml = $XMLInterfacer->toString($exportedStdObject); // return XML string
echo $xml;

output :

<person id="1" firstName="John" lastName="Doe">
    <mother>2</mother>
    <children>
        <child>3</child>
        <child>4</child>
    </children>
</person>

Foreign properties export

As you can see in previous example, value mother is exported as a simple id even if mother is actually an object. Foreign properties are exported like that for a simple reason, value can be defined elsewhere, and if we describe all object, same value would be described several times, it can be ambiguous and dangerous.

Interfacing preferences

You can define some preferences to apply during interfacing. All preferences have their constantes defined in Interfacer class.

privateContext

Summary

Define private context. Private properties are interfaced only in private context.

Description

type boolean
default false
avaibility import and export
constant Interfacer::PRIVATE_CONTEXT

Example

// here we suppose 'id' is a private property 
$person = new Object($model);
$person->setValue('id', 1);
$person->setValue('firstName', 'John');

$stdInterfacer = new StdObjectInterfacer();

$stdObject = $stdInterfacer->export($person);
echo $stdInterfacer->toString($stdObject);
// output '{"firstName":"John"}'

$stdObject = $stdInterfacer->export($person, [Interfacer::PRIVATE_CONTEXT => true]);
echo $stdInterfacer->toString($stdObject);
// output '{"id":1,"firstName":"John"}'

DEPRECATED

// merge (type merge is used by default if you don't specify it)
// if an object with same model and same id is found in MainObjectCollection get this instance 
// otherwise create a new one
// finally merge retrieved (or created) object with values to import
$person = $personModel->fromOject(json_decode('{"id":1,"firstName":"john","lastName":"doe"}'), Model::MERGE);

// overwrite
// if an object with same model and same id is found in MainObjectCollection get this instance and erase all values 
// otherwise create a new one
// finally fill retrieved (or created) object with values to import
$person = $personModel->fromOject(json_decode('{"id":1,"firstName":"john","lastName":"doe"}'), Model::OVERWRITE);

// no merge
// create a new instance even if an instance exists in MainObjectCollection
// finally fill created object with values to import
$person = $personModel->fromOject(json_decode('{"id":1,"firstName":"john","lastName":"doe"}'), Model::NO_MERGE);

Date time management

We have seen in Getting started page that a simple model dateTime exists so a property can have a type dateTime. A value with type dateTime will be an instance of DateTime. Using DateTime is a good practice, there are many date and time related functions and it can handle time zones.

Import and export

When you import or export object you can specify an optional parameter that define time zone that you want to work with (by default your PHP time zone is used).

// see php DateTime Constructor to know supported date time string formats
// use ISO 8601 format is a good practice
$person = $personModel->fromOject(json_decode('{"birthDate":"1988-05-01T14:53:54+02:00"}'), Model::MERGE, 'Europe/Paris');

$date = $person->getValue('birthDate'); // return instance of DateTime

// dateTime values are always exported in ISO 8601 format to encourage good practice
$person->toXml(false, 'Europe/Paris');

Database time zone

For most (all?) SGBD connection you can define your time zone. to set a specific time zone for your connection you must specify it in file config.json (by default time zone connection is UTC).
Whatever is your database time zone you don't have to take care of it, serialization/deserialization will automatically affect good time zone to all your values with type dateTime.

Clone this wiki locally