Data abstractions

I am re-thinking data providers and grids for Yii 3. In Yii 2 these were good but we can do better.

Yii 2 bad sides

  1. These were doing too much: working with request, getting data, validating data etc.
  2. These were tied to models and active record.

Code so far

Idea

The main idea is to represent data in a simple table form i.e. all items have same structure, each item has same named fields.

In order to support maximum number of data sources, data reader should not read data before read() is called i.e. we form reading criteria first and then applying it for reading. That allows to efficiently query SQL databases and alike sources with existing query language while not preventing to implement our own storages.

Interfaces

There are three main interface groups:

  1. DataProcessorInterface that allows unifying processing like batch processing.
  2. DataWriterInterface that allows writing data.
  3. DataReaderInteface and interfaces for its additional features that allow reading data:
  • CountableDataInterface - allows getting total number of items in data provider.
  • FilterableDataInterface - allows returning subset of items based on criteria.
  • SortableDataInterface - allows sorting by one or multiple fields.
  • OffsetableDataInterface - allows to skip first N items when reading data.

Sorting data

Sorting is similar to the one from Yii 2 except it doesn’t try to work with request:

$sort = (new Sort([ // <--- init with config
    'b' => [
        'asc' => ['bee' => SORT_ASC],
        'desc' => ['bee' => SORT_DESC],
        'default' => 'asc',
        'label' => 'B',
    ]
]))
    ->withOrder([ // <--- apply sorting
        'a' => 'desc',
        'b' => 'asc',
    ]);

There’s additional method for getting sorting from strings:

$sort->withOrderString(' -a, b'); // a DESC, b ASC

Sort object is passed to data reader before reading data and it affecting reading as part of criteria.

Filtering

This part I’m a bit stuck with. Currently there’s a set of criteria that are general enough under Reader\Criterion:

$criteria = new AndAll(
    new Compare('test', 42),
    new Compare('test2', 34),
    new OrAny(
        new LessThan('temperature', 10),
        new GreaterThan('temperature', 30)
    )
);

Since filter is likely to be set from JSON, passed in request parameter, the filter itself is separate and is accepting array:

$filter = new Filter($criteria->toArray());

The filter is passed to data reader and reader should return a subset of data based on it.

But there are problems with current code:

  1. Extensibility.
  2. Applying these criteria to concrete data reader isn’t simple.

This part I’d like to get ideas for and help most.

Pagination

There are two pagination types included. Offset, classical one and keyset. Data reader must implement a subset of reader interfaces in order to be used with these. Pagination classes are not working with request directly but providing easy way to set/get data.

3 Likes

Data providers, ORM, validation are pretty good in Yii2. I am thinking how to improve the performance of Yii3. Will it support connection pool or using Zephir / Swoole in some area of Yii3? Thanks a lot.

It will support RoadRunner and Swoole.

1 Like

What are the main problems Yii2 DataGrid:

  • Total, averarge and counting for footer row
  • From an optimization point of view, it is often enough to return a DataProvider record as an array instead of ActiveRecord
  • Data processing - For example use sql temporary tables or use php code for preparing data

If these problems are resolved in Yii3 Data grid, then no other solution is needed.

1 Like

Got it to working state with examples in readme. Please check if everything looks good.