Data
Robust and high performance PHP library for unified access to (not only) SQL databases
Install / Use
/learn @atk4/DataREADME
ATK Data - Data Model Abstraction for Agile Toolkit
Agile Data is a framework for defining your "business layer" which is separate from your "presentation layer" and "persistence". Together with Agile UI you can deliver user interface "out of the box" or with Agile API - general-purpose API endpoints.
- Agile Data uses PHP to define your Business Objects, their properties and actions.
- Agile Data works with SQL, NoSQL or external API sources.
- Agile Data plugs into generic UI components (Crud, Card, Table, Form, etc) with a minimum code.
- Agile Data supports "user actions". UI layer uses "action executor" to read ACL-controlled metadata.
- Agile Data is developer-friendly and easy to learn
- Agile Data is high-performance, capable of abstracting aggregation logic and shifting it into a capable database persistence (such as SQL) through advanced expressions.
- Agile Data is extensible - field types, persistence types, relations and action types can be extended.
Quick-Links: Documentation | Discord channel | ATK UI
Is ATK Data similar to ORM?
Yes and no.
Agile Data is data persistence framework - like ORM it helps you escape raw SQL. Unlike ORM, it maps objects into "data set" and not "data record". Operating with data sets offers higher level of abstraction:
$vipClientModel = (new Client($db))->addCondition('is_vip', true);
// express total for all VIP client invoices. The value of the variable is an object
$totalDueModel = $vipClientModel->ref('Invoice')->action('fx', ['sum', 'total']);
// single database query is executed here, but not before!
echo $totalDueModel->getOne();
In other ORM the similar implementation would be either slow, clumsy, limited or flawed.
How ATK Data integrates with UI (or API)
Agile Toolkit is a low-code framework. Once you have defined your business object, it can be associated with a UI widget:
Crud::addTo($app)->setModel(new Client($db), ['name', 'surname'], ['edit', 'archive']);
or with an API end-point:
$api->rest('/clients', new Client($db));
Extensibility and Add-ons
ATK Data is extensible and offers wide range of add-ons like Audit.
Regardless of how your model is constructed and what database backend is used, it can easily be used in conjunction with any 3rd party add-on, like Charts.
Benefits of using ATK Data
Designed for medium to large PHP applications and frameworks, ATK Data is a clean implementation of Data Mapper that will:
- Make your application really database-agnostic. SQL? NoSQL? RestAPI? Cache? Load and store your data with any of these, without refactoring your code.
- Execute more on the server. Agile Data converts query logic into server-specific language (e.g. SQL) then delivers you the exact data rows / columns which you need from a single statement, no matter how complex.
- Data architecture transparency. As your database structure change, your application code does not need to be refactored. Replace fields with expressions, denormalize/normalize data, join and merge tables. Only update your application in a single place.
- Extensions. "Audit" - transparently record all edits, updates and deletes with "Undo" support.
- Out of the box UI. Who wants to build Admin systems today? Tens of professional components: Crud, Grid, Form as well as add-ons like Charts can be added to your PHP app with 3-lines of code.
- RestAPI server for Agile Data is currently under development.
- Agile Data and all extensions mentioned above are licensed under MIT and are free to use.
Since the initial introduction of Agile Data back in 2016 our group of early-adopters used it in large production PHP projects. It is time for you to try Agile Data today.
Getting Started
Watch Quick Start or Screencasts. There is also Full Documentation (PDF).
ATK Data relies on ATK Core and can be greatly complimented by ATK UI:
- Agile Core - documents various low-level traits and features such as Containers, Hooks or Exceptions (PDF)
- Agile UI - documents optional UI components and how to build Web App with them. (PDF)
When to use Agile Data?
We believe that as a developer you should spend your time efficiently. Heavy-lifting your data is not efficient. Agile Data enables UI components, exporters, importers or RestAPI servers to be implemented in a generic way.
HTML Applications and Admin Systems
Most of the ORM (including the one you are probably using now) suffer from one flaw. As a framework they do not have enough information to describe models, fields, relations and conditions of your data model.

As a result the UI layer cannot simply discover how your Invoice relate to the Client. This makes YOU write a lot of glue code - performing query and feeding data into the UI layer.
With most ORMs you cannot design an generic Crud or Form which would work with ANY model. As a result server-side rendering becoming more extinct in the face of Client-side frameworks.
Agile Data addresses this balance. For the presentation logic you can use tools such as Agile UI, that consists of generic Crud, Form implementations or other modules which accept the Model protocol of Agile Data:
$presentation->setModel($businessModel);
This now re-shifts the balance and makes it possible to implement any generic UI Components, that will work with your custom data model and your custom persistence (database).

It's important to note, that glue may also interact with the model preparing it for a specific use-case:
$grid = new \Atk4\Ui\Table();
$data = new Order($db);
$data->addCondition('is_new', true);
$data->addCondition('client_id', $_GET['client_id']);
$grid->setModel($data);
$html = $grid->render();
Domain-Model Reports
Object Oriented approach was designed to hide the complexity of implementation. Yet, every time when you need data for the reports that include aggregation or joins, you must dive deep into your database structure to pull some quirky ORM hack or inject a custom SQL query.
Agile Data was designed in a way where all of your code can rely ONLY on model objects. This includes the reports.
This next example builds a complex "Job Profitability Report" by only relying on Model logic:
class JobReport extends Job
{
protected function init(): void
{
parent::init();
// Invoice contains Lines that may relevant to this job
$invoice = new Invoice($this->getPersistence());
// we need to ignore draft invoices
$invoice->addCondition('status', '!=', 'draft');
// build relation between job and invoice line
$this->hasMany('InvoiceLines', ['model' => static function () use ($invoice) {
return $invoice->ref('Lines');
}])
->addField('invoiced', [
'aggregate' => 'sum',
'field' => 'total',
'type' => 'atk4_money'
]);
// build relation between Job and Timesheets
$this->hasMany('Timesheets', ['model' => static function (Persistence $persistence) {
// next we need to see how much is reported through timesheets
$timesheet = new Timesheet($persistence);
// timesheet relates to client, import client.hourly_rate as expression
$timesheet->getReference('client_id')->addField('hourly_rate');
// calculate timesheet cost expression
$timesheet->addExpression('cost', ['expr' => '[hours] * [hourly_rate]']);
return $timesheet;
}])
->addField('reported', [
'aggregate' => 'sum',
'field' => 'cost',
'type' => 'atk4_money'
]);
// finally lets calculate profit
$this->addExpression('profit', ['expr' => '[invoiced] - [reported]']);
// profit margin could be also useful
$this->addExpression('profit_margin', ['expr' => 'coalesce([profit] / [invoiced], 0)']);
}
}
Your Report Model:
- moves query logic to the database (SQL)
- is still a model, so compatible with all UI Components and extensions
In order to output results on HTML table:
$grid = new \Atk4\Ui\Grid();
$data = new JobReport($db);
$grid->setModel($d
