### The Basics
DataTables consist of rows and each row consists of columns. A column value can be
a numeric, a string or an array.
Every row has an ID. The ID is either the index of the row or {@link ID_SUMMARY_ROW}.
DataTables are hierarchical data structures. Each row can also contain an additional
nested sub-DataTable (commonly referred to as a 'subtable').
Both DataTables and DataTable rows can hold **metadata**. _DataTable metadata_ is information
regarding all the data, such as the site or period that the data is for. _Row metadata_
is information regarding that row, such as a browser logo or website URL.
Finally, all DataTables contain a special _summary_ row. This row, if it exists, is
always at the end of the DataTable.
### Populating DataTables
Data can be added to DataTables in three different ways. You can either:
1. create rows one by one and add them through {@link addRow()} then truncate if desired,
2. create an array of DataTable\Row instances or an array of arrays and add them using
{@link addRowsFromArray()} or {@link addRowsFromSimpleArray()}
then truncate if desired,
3. or set the maximum number of allowed rows (with {@link setMaximumAllowedRows()})
and add rows one by one.
If you want to eventually truncate your data (standard practice for all Piwik plugins),
the third method is the most memory efficient. It is, unfortunately, not always possible
to use since it requires that the data be sorted before adding.
### Manipulating DataTables
There are two ways to manipulate a DataTable. You can either:
1. manually iterate through each row and manipulate the data,
2. or you can use predefined filters.
A filter is a class that has a 'filter' method which will manipulate a DataTable in
some way. There are several predefined Filters that allow you to do common things,
such as,
- add a new column to each row,
- add new metadata to each row,
- modify an existing column value for each row,
- sort an entire DataTable,
- and more.
Using these filters instead of writing your own code will increase code clarity and
reduce code redundancy. Additionally, filters have the advantage that they can be
applied to DataTable\Map instances. So you can visit every DataTable in a {@link DataTable\Map}
without having to write a recursive visiting function.
All predefined filters exist in the **Piwik\DataTable\BaseFilter** namespace.
_Note: For convenience, anonymous functions
can be used as DataTable filters._
### Applying Filters
Filters can be applied now (via {@link filter()}), or they can be applied later (via
{@link queueFilter()}).
Filters that sort rows or manipulate the number of rows should be applied right away.
Non-essential, presentation filters should be queued.
### Learn more
- See **{@link ArchiveProcessor}** to learn how DataTables are persisted.
### Examples
**Populating a DataTable**
adding one row at a time
$dataTable = new DataTable();
$dataTable->addRow(new Row(array(
Row::COLUMNS => array('label' => 'thing1', 'nb_visits' => 1, 'nb_actions' => 1),
Row::METADATA => array('url' => 'http://thing1.com')
)));
$dataTable->addRow(new Row(array(
Row::COLUMNS => array('label' => 'thing2', 'nb_visits' => 2, 'nb_actions' => 2),
Row::METADATA => array('url' => 'http://thing2.com')
)));
using an array of rows
$dataTable = new DataTable();
$dataTable->addRowsFromArray(array(
array(
Row::COLUMNS => array('label' => 'thing1', 'nb_visits' => 1, 'nb_actions' => 1),
Row::METADATA => array('url' => 'http://thing1.com')
),
array(
Row::COLUMNS => array('label' => 'thing2', 'nb_visits' => 2, 'nb_actions' => 2),
Row::METADATA => array('url' => 'http://thing2.com')
)
));
using a "simple" array
$dataTable->addRowsFromSimpleArray(array(
array('label' => 'thing1', 'nb_visits' => 1, 'nb_actions' => 1),
array('label' => 'thing2', 'nb_visits' => 2, 'nb_actions' => 2)
));
**Getting & setting metadata**
$dataTable = \Piwik\Plugins\Referrers\API::getInstance()->getSearchEngines($idSite = 1, $period = 'day', $date = '2007-07-24');
$oldPeriod = $dataTable->metadata['period'];
$dataTable->metadata['period'] = Period\Factory::build('week', Date::factory('2013-10-18'));
**Serializing & unserializing**
$maxRowsInTable = Config::getInstance()->General['datatable_archiving_maximum_rows_standard'];j
$dataTable = // ... build by aggregating visits ...
$serializedData = $dataTable->getSerialized($maxRowsInTable, $maxRowsInSubtable = $maxRowsInTable,
$columnToSortBy = Metrics::INDEX_NB_VISITS);
$serializedDataTable = $serializedData[0];
$serailizedSubTable = $serializedData[$idSubtable];
**Filtering for an API method**
public function getMyReport($idSite, $period, $date, $segment = false, $expanded = false)
{
$dataTable = Archive::getDataTableFromArchive('MyPlugin_MyReport', $idSite, $period, $date, $segment, $expanded);
$dataTable->filter('Sort', array(Metrics::INDEX_NB_VISITS, 'desc', $naturalSort = false, $expanded));
$dataTable->queueFilter('ReplaceColumnNames');
$dataTable->queueFilter('ColumnCallbackAddMetadata', array('label', 'url', __NAMESPACE__ . '\getUrlFromLabelForMyReport'));
return $dataTable;
}