Skip to content

Commit

Permalink
Fixed activeDropDownList and added docs on ORMAdapters
Browse files Browse the repository at this point in the history
  • Loading branch information
codespede committed Nov 14, 2021
1 parent bfa2cec commit 46251c6
Show file tree
Hide file tree
Showing 6 changed files with 355 additions and 127 deletions.
171 changes: 58 additions & 113 deletions docs/output-data-providers.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
Data Providers
==============
# Data Providers

In the [Pagination](/pwoli/api-docs/classes/Pagination.html) and [Sort](/pwoli/api-docs/classes/Sort.html) sections, we have described how to
allow end users to choose a particular page of data to display and sort them by some columns. Because the task
of paginating and sorting data is very common, Pwoli provides a set of *data provider* classes to encapsulate it.
of paginating and sorting data is very common, Pwoli provides a set of _data provider_ classes to encapsulate it.

A data provider is a class extending [DataProvider](/pwoli/api-docs/classes/DataProvider.html). It mainly supports retrieving paginated
and sorted data. It is usually used to work with [data widgets](/pwoli/output-data-widgets.md) so that end users can
interactively paginate and sort data.
and sorted data. It is usually used to work with [data widgets](/pwoli/output-data-widgets.md) so that end users can
interactively paginate and sort data.

The following data provider classes are included in the Pwoli releases:

* [ActiveDataProvider](/pwoli/api-docs/classes/ActiveDataProvider.html): uses [query](/pwoli/api-docs/classes/ActiveDataProvider.html#query) to query data from databases
and return them in terms of arrays or [Active Record](/pwoli/api-docs/classes/Model.html) instances.
* [ArrayDataProvider](/pwoli/api-docs/classes/ArrayDataProvider.html): takes a big array and returns a slice of it based on the paginating and sorting
specifications.
- [ActiveDataProvider](/pwoli/api-docs/classes/ActiveDataProvider.html): uses [query](/pwoli/api-docs/classes/ActiveDataProvider.html#query) to query data from databases
and return them in terms of arrays or [Active Record](/pwoli/api-docs/classes/Model.html) instances.
- [ArrayDataProvider](/pwoli/api-docs/classes/ArrayDataProvider.html): takes a big array and returns a slice of it based on the paginating and sorting
specifications.

The usage of all these data providers share the following common pattern:

Expand All @@ -35,7 +34,7 @@ let count = provider.getCount();
let totalCount = provider.getTotalCount();
```

You specify the pagination and sorting behaviors of a data provider by configuring its
You specify the pagination and sorting behaviors of a data provider by configuring its
[pagination](/pwoli/api-docs/classes/DataProvider.html#pagination) and [sort](/pwoli/api-docs/classes/DataProvider.html#sort) properties
which correspond to the configurations for [Pagination](/pwoli/api-docs/classes/Pagination.html) and [Sort](/pwoli/api-docs/classes/Sort.html), respectively.
You may also configure them to be `false` to disable pagination and/or sorting features.
Expand All @@ -52,18 +51,18 @@ let grid = new GridView({

In the [Pagination](/pwoli/api-docs/classes/Pagination.html) and [Sort](/pwoli/api-docs/classes/Sort.html) sections, we have described how to
allow end users to choose a particular page of data to display and sort them by some columns. Because the task
of paginating and sorting data is very common, Pwoli provides a set of *data provider* classes to encapsulate it.
of paginating and sorting data is very common, Pwoli provides a set of _data provider_ classes to encapsulate it.

A data provider is a class implementing [DataProvider](/pwoli/api-docs/classes/DataProvider.html). It mainly supports retrieving paginated
and sorted data. It is usually used to work with [data widgets](/pwoli/output-data-widgets.md) so that end users can
interactively paginate and sort data.
and sorted data. It is usually used to work with [data widgets](/pwoli/output-data-widgets.md) so that end users can
interactively paginate and sort data.

The following data provider classes are included in the Pwoli releases:

* [ActiveDataProvider](/pwoli/api-docs/classes/ActiveDataProvider.html): uses [query](/pwoli/api-docs/classes/ActiveDataProvider.html#query) to query data from databases
and return them in terms of arrays or [Active Record](/pwoli/api-docs/classes/Model.html) instances.
* [ArrayDataProvider](/pwoli/api-docs/classes/ArrayDataProvider.html): takes a big array and returns a slice of it based on the paginating and sorting
specifications.
- [ActiveDataProvider](/pwoli/api-docs/classes/ActiveDataProvider.html): uses [query](/pwoli/api-docs/classes/ActiveDataProvider.html#query) to query data from databases
and return them in terms of arrays or [Active Record](/pwoli/api-docs/classes/Model.html) instances.
- [ArrayDataProvider](/pwoli/api-docs/classes/ArrayDataProvider.html): takes a big array and returns a slice of it based on the paginating and sorting
specifications.

The usage of all these data providers share the following common pattern:

Expand All @@ -84,7 +83,7 @@ let count = provider.getCount();
let totalCount = provider.getTotalCount();
```

You specify the pagination and sorting behaviors of a data provider by configuring its
You specify the pagination and sorting behaviors of a data provider by configuring its
[pagination](/pwoli/api-docs/classes/DataProvider.html#pagination) and [sort](/pwoli/api-docs/classes/DataProvider.html#sort) properties
which correspond to the configurations for [Pagination](/pwoli/api-docs/classes/Pagination.html) and [Sort](/pwoli/api-docs/classes/Sort.html), respectively.
You may also configure them to be `false` to disable pagination and/or sorting features.
Expand All @@ -101,18 +100,17 @@ let grid = new GridView([
These data providers mainly vary in the way how the data source is specified. In the following subsections,
we will explain the detailed usage of each of these data providers.


## Active Data Provider <span id="active-data-provider"></span>
## Active Data Provider <span id="active-data-provider"></span>

To use [ActiveDataProvider](/pwoli/api-docs/classes/ActiveDataProvider.html), you should configure its [query](/pwoli/api-docs/classes/ActiveDataProvider.html#query) property.
It can take a [query](/pwoli/api-docs/classes/ActiveDataProvider.html#query) object. If the former, the data returned will be arrays;
if the latter, the data returned can be either arrays or [Active Record](/pwoli/api-docs/classes/Model.html) instances.
For example,

```js
import { ActiveDataProvider} from 'pwoli';
import { ActiveDataProvider } from 'pwoli';

let query = where({status: 1});
let query = where({ status: 1 });

let provider = new ActiveDataProvider({
query: {},
Expand All @@ -122,8 +120,8 @@ let provider = new ActiveDataProvider({
sort: {
defaultOrder: {
created_at: SORT_DESC,
title: SORT_ASC,
}
title: SORT_ASC,
},
},
});

Expand All @@ -136,17 +134,16 @@ If `query` in the above example is created using the following code, then the da
```js
import Query;

let query = ({where: {status: 1}});
let query = ({where: {status: 1}});
```

> Note: If a query already specifies the `orderBy` clause, the new ordering instructions given by end users
(through the `sort` configuration) will be appended to the existing `orderBy` clause. Any existing `limit`
and `offset` clauses will be overwritten by the pagination request from end users (through the `pagination` configuration).
> (through the `sort` configuration) will be appended to the existing `orderBy` clause. Any existing `limit`
> and `offset` clauses will be overwritten by the pagination request from end users (through the `pagination` configuration).
By default, [ActiveDataProvider](/pwoli/api-docs/classes/ActiveDataProvider.html) uses the `db` application component as the database connection. You may
use a different database connection by configuring the [db](/pwoli/api-docs/classes/ActiveDataProvider.html#db) property.


## Array Data Provider <span id="array-data-provider"></span>

[ArrayDataProvider](/pwoli/api-docs/classes/ArrayDataProvider.html) is best used when working with a big array. The provider allows you to return
Expand Down Expand Up @@ -178,22 +175,21 @@ let provider = new ArrayDataProvider({

// get the rows in the currently requested page
let rows = provider.getModels();
```

> Note: Compared to [Active Data Provider](#active-data-provider),array data provider is less efficient because it requires loading *all* data into the memory.
```

> Note: Compared to [Active Data Provider](#active-data-provider),array data provider is less efficient because it requires loading _all_ data into the memory.
## Working with Data Keys <span id="working-with-keys"></span>

When using the data items returned by a data provider, you often need to identify each data item with a unique key.
For example, if the data items represent customer information, you may want to use the customer ID as the key
for each customer data. Data providers can return a list of such keys corresponding with the data items returned
for each customer data. Data providers can return a list of such keys corresponding with the data items returned
by [DataProvider.getModels()](/pwoli/api-docs/classes/DataProvider.html#getModels). For example,

```js
import { ActiveDataProvider } from 'pwoli';

let query = {where: {status: 1}};
let query = { where: { status: 1 } };

let provider = new ActiveDataProvider({
query: {},
Expand Down Expand Up @@ -223,23 +219,22 @@ provider = new ActiveDataProvider({
query: {},
key: function (model) {
return md5(model.id);
}
},
});
```


## Creating Custom Data Provider <span id="custom-data-provider"></span>

To create your own custom data provider classes, you should implement [DataProvider](/pwoli/api-docs/classes/DataProvider.html).
An easier way is to extend from [DataProvider](/pwoli/api-docs/classes/DataProvider.html) which allows you to focus on the core data provider
logic. In particular, you mainly need to implement the following methods:
- [prepareModels](/pwoli/api-docs/classes/DataProvider.html#prepareModels): prepares the data models that will be made
available in the current page and returns them as an array.
- [prepareKeys](/pwoli/api-docs/classes/DataProvider.html#prepareKeys): accepts an array of currently available data models
and returns keys associated with them.
- [PrepareTotalCount](/pwoli/api-docs/classes/DataProvider.html#prepareTotalCount): returns a value indicating the total number
of data models in the data provider.

- [prepareModels](/pwoli/api-docs/classes/DataProvider.html#prepareModels): prepares the data models that will be made
available in the current page and returns them as an array.
- [prepareKeys](/pwoli/api-docs/classes/DataProvider.html#prepareKeys): accepts an array of currently available data models
and returns keys associated with them.
- [PrepareTotalCount](/pwoli/api-docs/classes/DataProvider.html#prepareTotalCount): returns a value indicating the total number
of data models in the data provider.

Below is an example of a data provider that reads CSV data efficiently:

Expand All @@ -252,37 +247,37 @@ class CsvDataProvider extends DataProvider
* @var string name of the CSV file to read
*/
public filename;

/**
* @var string|callable name of the key column or a callable returning it
*/
public key;

/**
* @var SplFileObject
*/
protected fileObject; // SplFileObject is very convenient for seeking to particular line in a file


/**
* {@inheritdoc}
*/
public function init()
public init()
{
parent.init();

// open file
this.fileObject = new SplFileObject(this.filename);
}

/**
* {@inheritdoc}
*/
protected function prepareModels()
protected prepareModels()
{
models = [];
pagination = this.getPagination();

if (pagination === false) {
// in case there's no pagination, read all lines
while (!this.fileObject.eof()) {
Expand All @@ -294,106 +289,56 @@ class CsvDataProvider extends DataProvider
pagination.totalCount = this.getTotalCount();
this.fileObject.seek(pagination.getOffset());
limit = pagination.getLimit();

for (count = 0; count < limit; ++count) {
models[] = this.fileObject.fgetcsv();
this.fileObject.next();
}
}

return models;
}

/**
* {@inheritdoc}
*/
protected function prepareKeys(models)
protected prepareKeys(models)
{
if (this.key !== null) {
keys = [];

foreach (models as model) {
if (is_string(this.key)) {
keys[] = model[this.key];
} else {
keys[] = call_user_func(this.key, model);
}
}

return keys;
}

return array_keys(models);
}

/**
* {@inheritdoc}
*/
protected function prepareTotalCount()
protected prepareTotalCount()
{
count = 0;

while (!this.fileObject.eof()) {
this.fileObject.next();
++count;
}

return count;
}
}
```

## Filtering Data Providers using Data Filters <span id="filtering-data-providers-using-data-filters"></span>
## Filtering Data Providers <span id="filtering-data-providers"></span>

While you can build conditions for active data provider manually as described in
You can easily build conditions for filtering data with active data provider manually as described in
[Filtering Data](/pwoli/output-data-widgets.md#filtering-data) and [Separate Filter Form](/pwoli/output-data-widgets.md#separate-filter-form)
sections of data widgets guide, Pwoli has data filters that are very useful if you need flexible filter conditions.
Data filters could be used as follows:

```js
let filter = new ActiveDataFilter({
searchModel: 'app\models\PostSearch'
});

let filterCondition = null;

// You may load filters from any source. For example,
// if you prefer JSON in request body,
// use Pwoli.app.request.getBodyParams() below:
if (filter.load(\Pwoli.app.request.get())) {
filterCondition = filter.build();
if (filterCondition === false) {
// Serializer would get errors out of it
return filter;
}
}

let query = {};
if (filterCondition !== null) {
query.andWhere(filterCondition);
}

return new ActiveDataProvider({
query: {},
});
```

`PostSearch` model serves the purpose of defining which properties and values are allowed for filtering:

```js
import { Model } from 'pwoli';

class PostSearch extends Model
{
public id;
public title;

public function rules()
{
return [
['id', 'integer'],
['title', 'string', {min: 2}, {max: 200}],
];
}
}
```
Loading

0 comments on commit 46251c6

Please sign in to comment.