Agile Data

2016-10-24 17:38:10
PHP Framework for better Business Logic design and scalable database access
PHP Data Access Libraries (ORM, ActiveRecord, Persistence)
Agile Data
Github / Bitbucket / Sourceforge
Latest version1.1.x
How schema is defined?method init() in Model class defines fields, relations, conditions, etc.
Code generation- Planned.
Can be used in Any FrameworkYes Through composer/packagist
Automated Cache- Planned
Anti-patterns (purposely included)SRP in Model. Implements Scopes and Active Record.
DependenciesMinimal: 2 packages: DSQL Query Builder (
Simplicity5.0 1 rating
Enterprise Compliance5.0 1 rating
Minimum PHP Version5.6
Basic Features
PDO SupportYes MySQL, SQLite, Others
NoSQL Integrate Transparently- Supported, but drivers not provided.
How to invoke db-vendor-specific extensions?Yes Provides access to persistence-layer actions (Queries)
Array as a persistenceYes CRUD operations supported
RestAPI as a persistence- Planned
JSON string as a persistence- In development
Same model, multiple persistencesYes Same class. Different object.
Persistence Mapping (must support C,R,U,D)
Table Name MappingYes $model->table = 'my_table'
Field Name MappingYes PHP: "name" = SQL: "first_name"
Map Entity to SubQueryYes "Table" can be "Expression" (or another Model)
Map property to expressionYes $model->addExpression()
Map native types (DateTime)Yes $field->type = 'date'
User-defined types (e.g. "23 USD")Yes Through typecasting
Map field of related Entity ('currency' = currency_id->Model Maps into sub-query.
Map field to sub-query on related entity (Client.balance = Client->orders->sum(total))Yes hasMany()->addField(..aggregate)
Entity to join multiple tables (adding new record populates both tables)Yes $model->join('other_table')
NoSQL (must be transparent to domain logic)
MongoDB support- Planned
Neo4j- Planned
MemCache- Planned
Criteria, Scope, Conditions (Model will refuse to work with records that does not match criteria)
Support model-level criteriaYes
Soft-delete- Easy to implement through conditions. See docs.
Domain Model CriteriaYes $m->addCondition('gender','M')
Expression-based conditionYes $m->addCondition($m->expr('..'));
Criteria Compliance (new record must match condition)Yes With reloading and rollback
Dynamic criteriaYes $user->addCondition('is_expired', false)
Query Building (Convert Model into Query object for further SQL tweaking)
Convert Model into Query ObjectYes $q = $model->action('select');
Raw expressionYes new Expression('any sql')
Nested/Composite Queries/ExpressionsYes Expression can be in any part of query
Reference domain-model field in queryYes through Expressionable interface
field, where, order, limitYes Expressions and Parametric values
options, rollup, partition- Through custom templates, or expressions.
UPDATE, DELETE, INSERT query buildingYes
SHOW, DESCRIBE, CALL- Supported through Expressions or Custom query template
ALTER, CREATE query buildingYes Addon:
User-defined query templateYes Templates for all queries
OR deep nested conditionsYes Through Object Composition
Use Domain logic in multi-record update- Supported, but must map fields/values manually.
Data Fetching (different ways to retrieve data from database)
Get All Data (2x array)Yes
Associative Array (id=>value)No Planned
Single rowYes loadAny
Single Value- Through action
Single ColumnNo Planned
Bypass persistence mappingYes action('select')->getAll()
Loading and Saving individual records
Load by IDYes load(id)
Load by other fieldYes loadBy('field', $value)
Load if expressionYes loadBy($expression)
Load respects Scope (model-level condition)Yes All conditions added as "where" clause
Specify fields to loadYes onlyFields()
Save only sends dirty fieldsYes
Guarded / Fillable properties- Conditions and OnlyFields do same thing differently.
Object Hierarchy Model
Admin extends User (is_admin=1)Yes Yes, recommended pattern. "User" class adds condition.
Model that represent Orders of single User.Yes Yes, recommended pattern.
Extend model, add Join (Disjoined SubTypes)Yes Yes. Unlimited number of joins.
Extend model change tableYes Yes. Used to tweak 3rd party models.
Relations/References (One model can relate to another model. NOT A TABLE JOIN)
Model can define relation to other ModelYes References are implemented as Objects
One-to-ManyYes $user->hasMany('Orders', new Order());
One-to-many traversal strategyReturns destination model instance with dynamically applied criteria (parent_id=123). No queries are executed. Inserting record into this model will ensure association with parent model.
Lazy/Eager-loadingNo Anti-pattern
One-to-OneYes $order->hasOne('user_id', new User());
Many-to-ManyYes $user->addCondition('vip', true)->ref('Orders');
Deep Many-to-Many traversal.Yes $user->ref('Orders')->ref('Payments')->action('count'); No intermediate queries.
Cross-Persistence traversalYes $user->hasMany('Log', new Log($mongodb));
Multi-persistence Mapping (some data from SQL, others MongoDB)
Multi-persistence join- Planned.
UNION existing models- Planned
Multi-persistence UNIONNo But you can merge raw data
Multi-persistence value linking (current_sensor_value)- Through 'afterLoad' hook.
Behaviours / Hooks
Before/After operationYes
Hooks for C,R,U,D operationsYes
Persistence-specific hooks (to modify Query)Yes
User-defined hooksYes
Mapping strategyRecord dirty fields before persisting. Type-cast into JSON string and store in a single field of AuditLog Model. This model can be persisted anywhere, table, file, etc.
How to set-upAuditLog can be enabled for all models associated with a specific persistence. No further changes are necessary. Works out of the box.
Store old/new field valuesYes Yes in JSON and user-readable string.
Date of creation, modification- No but easy to add through hook.
User/IP creation, modification- Easy to add through a hook.
Store incremental revisions- Easy to add through a hook
Revert action (undo)Yes
Custom eventsYes
Custom fields, tableYes Remove default fields, use your own table, fields, formats.
Store in CSV- Planned
Access to record-specific historyYes $item->ref('AuditLog');
Access Control
Implementation StrategyDefine a special DB-hook. Every time new "Model" is initialized, extra "condition" will be added. This will make sure that you won't forget some important condition when traversing references. You can also restrict access to edit/delete through per-model hooks that can be globally set.
Single-system global access scopeYes Define "system_id" for all models that have this field defined - this will create global condition for all models making sure that user can work with records of one system at a time.
Meta-information (allows exploration by UI widgets)
Implementation StrategyAgile Data is designed to work with UI toolkits. Generic widgets can explore model fields and various meta-information about those fields. References are easy to identify and traverse allowing DropDown fields to populate values inside select.
UI Widget can fetch list of Model FieldsYes
UI Widget can get Field type, default value, caption, hintYes
field storing reference to another Model can map into DropDownYes Widget can discover references and traverse to fetch list of drop-down options. Model defines "title_field" which is used by default.
Like 1
  • 2016-10-18 22:11:55
    2016-10-24 17:38:10
  • Products
  • Public
  • Creative Commons License CC-BY-SA 3.0 / GNU FDL


Leave a comment

Build comparison tables or lists about everything !

It's free and fast to publish data into original tables

Create a table