Skip to content
bggardner edited this page May 29, 2012 · 14 revisions

Table of Contents

Introduction

As mentioned in the README, moxim-php is my attempt at implementing the Modular eXtensible Information Modeler (MoXIM) concept. The original XIM was essentially schema-less, as all the data and the relationships between them were dynamic. In other words, there was no defined structure (fields/columns) for any type of data. On the other side of the spectrum is a fully defined schema, where all the data fields are defined and relationships between them are only captured in foreign key relationships. MoXIM is in the middle of the spectrum, allowing schemas to be defined for simplification and efficiency, but maintaining the flexibility of creating dynamic relationships without predefined foreign keys.

Terminology

General

  • A Module is simply a data structure (table) that uses MoXIM. A table can exist in a database, but is not a MoXIM Module unless it is listed in the Modules Module (see Base Modules). A Module has a defined schema.
  • A Node is simply a data item (row) in a Module.
  • A Relationship is defined between two Nodes. Normally these Nodes are in different Modules, but can be in the same Module. A Relationship is directional, with the domain being the source Node and the range being the target Node.
  • A Relation defines the type of Relationship between two modules. The domain of the Relation is the source module and the range is the target module.
  • An Assignment is defined between a Node and a scalar value. By itself, the application of this Module is limited, but when used with the proposed Properties and Property_Types (see Proposed Modules), its purpose becomes clear.

Data Access

In moxim-php, MoXIM data is packaged in Models which define their schema. These Models are passed to a Service layer which perform basic validation and error checking, which then passes the Models to a Data Provider layer. The Data Providers perform database-specific functions, such as escaping strings to prevent injection, making the calls to the database, and returning any data as Models. In other words, models provide data abstraction, and Services and Data Providers provide database abstraction.

Internal Modules

Base Modules

  • Modules
    • Fields: id, name
    • Provides index for other Modules to reference
  • Relations
    • Fields: id, domain (FK to Modules.id), name, range (FK to Modules.id)
    • Provides index for Relationship types
  • Relationships
    • Fields: id, domain (FK to [module].id), relation (FK to Relations.id), range (FK to [module].id)
    • Creates an instance of a Relation between two nodes.
  • Assignments
    • Fields: id, module (FK to Modules.id), node (FK to [module].id), value
    • Assigns a value to a Node in a given Module.

Proposed Modules

Properties/Property_Types

  • Property_Types fields: id, unit, abbr (abbreviation for unit), parent (FK to Property_Types.id)
  • Properties fields: id, name, type (enumeration or FK to Property_Types.id for hierarchy)
This will allow for assignments to be meaningful, giving the value a data type. If self-referencing foreign keys are used for Property_Types, the first entries would be the PHP scalar data types: boolean, integer, float, and string. These would have NULL types. This would allow for Property_Types to be hierarchical, though the Hierarchies Module (see below) could be used instead. If an enumeration is used, the type field would be one of the scalar data types.

Example: Assign the "Length" property of a Node to a value of 3.14 meters in a user Module.

  • Property_Types: id=5, unit="meters", abbr="m", type="float"
  • Properties: id=1, name="Length", type=5
  • Relations: id=1, domain=[Modules.id], name="has", range=[Modules.id]
  • Relationships: id=1, domain=[Node.id], relation=1, range=1
  • Assignments: id=1, module=[Modules.id], node=[Node.id], value="3.14"
  • Subsequent assignments for the "Length" property only require additions to the Relationships and Assignments Modules.

Permissions

  • Fields: id, module (FK to Modules.id), node (NULL or 0 for all), permissions (0 = none | 1 = read | 3 = write)
The Permissions Module stores read/write permissions for each Module. A roles Module could list roles, and permissions can be applied to roles via Relationships. Roles can then be applied to a user Module via Relationships. Permissions could also be applied to users directly.

Hierarchies

  • Fields: id, module (FK to Modules.id), node (FK to [module].id), relative (FK to [module].id) , distance
  • Stores hierarchy in flat table, no need for walking.
  • 2 entries for each relationship (bidirectional)
    • Entry 1: node = descendant, relative = ancestor, distance=positive number of generations/levels apart
    • Entry 2: node = ancestor, relative = descendant, distance=negative number of generations/levels apart
  • Siblings are determined by common (relative, distance) combination

File Structure

/app/config.php: Required configuration file for moxim-php

/app/index.php: A general administration GUI for moxim-php

/lib/models/: Models - must extend ./Node

/lib/services/: Services - must extend ./BaseService

/lib/services/dataproviders/: Data source initialization, point to Gateways or DAOs

/lib/services/dataproviders/daos: Data Access Objects, one for each Model, must extend ./Node

/lib/services/dataproviders/gateways: Gateways, must implement ./IBaseGateway

Considerations

Indexes

There are three ways to determine the primary index of a user Module:

  • Force the user to use "id"
  • Force the user to use the first field
  • Look up dynamically via the database schema
For the first two options, an auxiliary table can be used to re-index the user Module.

Example: [user_module_aux] has fields: id, user_module_index (user_module.[index] FK)

The third option is much more complicated and inefficient. Module indexes (node ids) would have to be stored as strings instead of unsigned integers for the second and third options. Therefore, the first option would be best, even if it means using the auxiliary tables. This is the current option used in moxim-php.

Domain/Range/Source/Target

Domain and range were used in XIM for Relations and Relationships, but MoXIM uses source and target.

Data Provider Initialization

Consider changing initialization from an stdClass object to an associative array, or a defined Model.