Agile Data

2017-12-20 01:05:19
Data Access Framework for high-latency databases (Cloud SQL/NoSQL).
PHP Data Access Libraries (ORM, ActiveRecord, Persistence)
Agile Data
Github / Bitbucket / Sourceforge
Latest version1.2.x
How schema is defined?in PHP. Method init() in Model class defines fields, relations, conditions, etc.
Code generationYes
Can be used in Any FrameworkYes Through composer/packagist
Automated CacheYes Frameworks focuses on optimizing queries rather then caching. Still possible with cross-persistence saving.
Anti-patterns (purposely included)Model close-coupled with Persistence and Field classes.
DependenciesMinimal: 2 packages: DSQL Query Builder (
Simplicity5.0 2 ratings
Enterprise Compliance5.0 2 ratings
Minimum PHP Version5.6
Basic Features
PDO SupportYes Yes
Transparent support for NoSQL- Through 3rd party drivers.
How to invoke db-vendor-specific extensions?Yes For SQL - save/load/delete operations are expressed in DSQL Queries that can be manipulated:
Array as a persistenceYes CRUD operations supported
RestAPI as a persistence- Through 3rd party extension.
JSON string as a persistenceYes Supported with few extra lines of code.
Same model, multiple persistencesYes Same class. Different object.
Basic Single-record operations (C,R,U,D)
Table Name MappingYes Yes
Field Name MappingYes Yes (Field::actual property)
Map Entity to SubQueryYes Yes. Extension exist for UNION-models.
Map property to expressionYes $model->addExpression()
Map native types (DateTime)Yes $field->type = 'date'
User-defined types (e.g. "23 USD")Yes Yes. Independent from Model. by extending Field class.
Map field of related Entity ('currency' = currency_id->Model Transparently maps into sub-select.
Map field to sub-query on related entity (Client.balance = Client->orders->sum(total))Yes Yes. hasMany()->addField(..aggregate)
Entity to join multiple tables (adding new record populates both tables)Yes $model->join('other_table')
Criteria, Scope, Conditions (Model will refuse to work with records that does not match criteria)
Support model-level criteriaYes Yes. Applied on loading / saving / update.
Soft-deleteYes Through criteria. Example given in the docs.
Domain Model CriteriaYes $m->addCondition('gender','M'); where 'gender' can be arbitrary expression, sub-select, field from association(join) or mapped no another physical field.
Expression-based conditionYes $m->addCondition($m->expr('..'));
Criteria Compliance (new record must match condition)Yes Transaction rollback and exception. Automated-rloading.
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
full support for OR conditionsYes Through Object Composition and Expressions
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
Select only required fieldsYes
Typecasting (e.g. DateTime)Yes
Import (multiple records)Yes
Respect domain model mapping (and criteria)Yes
Single rowYes loadAny
Single ValueYes Through action
Single Column- may need to map resulting array
Bypass persistence mappingYes action('select')->getAll()
Loading and Saving individual records
Load by IDYes load(id)
Load by other fieldYes loadBy('field', $value)
Read-only ModelsYes Yes
Model without primary keyYes Yes, but only in Read-only Mode
Specify fields to loadYes onlyFields()
Save only sends dirty fieldsYes
Guarded / Fillable propertiesYes Conditions and OnlyFields do same thing but more reliably.
Object Hierarchy Model
Admin extends User, adds criteria (is_admin=1)Yes Yes, recommended pattern. "User" class adds condition.
Admin extends User, adds accessible fieldsYes 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));
Cross-persistence joins, aggregation, reporting
Multi-persistence joinNo
UNION existing modelsYes Yes, in add-on Can join UNION result with more tables.
Domain-model AggregationYes Group by multiple fields. Apply aggregation functions. Preserve types.
Model to Model joinNo Planned.
Multi-persistence UNIONNo
Behaviours / Hooks
Before/After operationYes
Override standard C,R,U,D operationsYes
Persistence-specific hooks (to modify Query)Yes
User-defined hooksYes
Global AuditingYes
Store old/new field valuesYes Yes in JSON and user-readable string.
Revert action (undo) and replay (redo)Yes
Reactive actionsYes Each action will be automatically linked with sub-actions which may be invoked through Hooks.
Store log in any persistenceYes
Override, Add fields to audit logRecord 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.
Custom eventsYes
Access to record-specific historyYes $item->ref('AuditLog');
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
Field meta-information providedType, caption, possible values, mapped field, join table spec, encryption, serialization, UI-specific settings, validation rules.
UI extensionsYes CRUD, Form, Table, Grid, Entity-manager. (see
API extensionsYes RestFULL API, automated CRUD operations + RPC
Like 2
  • 2016-10-18 22:11:55
    2017-12-20 01:05:19
  • Products
  • Public
  • Creative Commons License CC-BY-SA 3.0 / GNU FDL


  • voted for this Item (Like)
    Couldn't work on any other framework/orm after switching to ATK. Its just how every programmer always wanted ...
    Posted 2016-10-25 19:16:29 by Gowrav
  • rated this Item: Enterprise Compliance 5
    Using in Recent modules of our ERP
    Posted 2016-10-25 18:51:02 by Gowrav
  • rated this Item: Simplicity 5
    Most simple among what I used (almost all popular ones)
    Posted 2016-10-25 18:50:37 by Gowrav
  • voted for this Item (Like)
    Not really an ORM, but offers much more powerful support for Domain Model.
    Posted 2016-10-24 02:18:39 by Romans Malinovskis
  • rated this Item: Enterprise Compliance 5
    Posted 2016-10-18 22:34:27 by Romans Malinovskis
  • rated this Item: Simplicity 5
    Posted 2016-10-18 22:14:01 by Romans Malinovskis

Leave a comment

Build comparison tables or lists about everything !

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

Create a table