The Cycle ORM architecture separates entity representation (data carrying object), entity data (node) and current data changes (state). In the simplest form the entity lifecycle can be describe as following:
The Entity object is, technically, any object used to carry data (including relation data). By default Cycle relies on separate classes for each of the entities, however, it is possible to use
stdClass or the same class for multiple entities. This can be achieved by associating the entity with custom mappers and giving them different roles. Upon
persist operation, the Mapper object must extract entity values and generate the desired State associated with entity Node.
Since the extraction and hydration of an entity is controlled solely by its associated Mapper, it is possible to use custom entity implementations, such as ActiveRecord-like classes, or entities in which data is represented using an internal array structure.
A node is an internal object used to represent any entity in the system. The node is only used to carry entity information such as a current set of relations, entity role and it's persisted data. Each entity always has one Node object associated with it (however, Node might not exist till the first persist operation).
Node State represents changes generated by mappers and is used to represent the desired state of the data. In addition to that, State links some of the entity fields to the external contexts (for example FK from the relation). The State exists only during the transaction lifecycle.
If the transaction succeeds the State data will be merged with parent Node object to sync Heap state with persistent storage. In case of transaction failure the State will be deleted, keeping the Node in its original (pre-transaction) form.
The Heap is used to store all loaded entity Nodes and their current states (if any). By design, heap operates as a hash table in which the entity is the key and node is the value.
A transaction used to generate and run a set of operations required to persist or delete given entities. Though all of the operations are performed within a single Heap the changes are never written to Node directly and only synced once the transaction is complete.
Command is a state-changing event applied to the persistence layer. Commands can depend on values in the state which are provided by other commands (relations). The transaction sorts commands by their dependencies iteratively, executing every command which does not have any unsatisfied dependency. Command execution might or might not resolve one of the multiple dependencies.