Dynamic Table System Documentation
This system helps manage table by simplifying pagination, sorting, and filtering.
System Overview
The dynamic table system is based on three main classes:
- ModelList: Manages the database connection and generates queries based on request parameters.
- ListStructure: Manages the column structure of a table.
- PageInfo: Manages pagination and display information.
1. ModelList Class
The ModelList class helps manage the display of HTML tables from a MySQL table. It allows you to define the column structure and manage data sorting and pagination.
Public Functions of ModelList
__construct($table, $table_id = null)
Class constructor. Initializes the table.
// Creates a ModelList instance for the specified table
$model = new \App\Modellist\ModelList('#__dynamic_example');
// Creates an instance with a custom ID
$model = new \App\Modellist\ModelList('#__dynamic_example', 'my-table-id');
setListStructure($list_structure)
Sets the column structure of the table. Accepts an array or a ListStructure instance.
// Usage with an array
$model->setListStructure([
'id' => ['type' => 'text', 'label' => 'ID', 'primary' => true],
'title' => ['type' => 'text', 'label' => 'Title']
]);
// Usage with a ListStructure instance
$listStructure = new App\Modellist\ListStructure();
$listStructure->setColumn('id', 'ID', 'text', true, true);
$listStructure->setColumn('title', 'Title', 'text', true, false);
$model->setListStructure($listStructure);
getListStructure($columns, $primary_key)
Returns a ListStructure instance with the table's column structure. If not set, it is automatically generated based on the table fields.
It is used to generate the table structure from the database table. If $rows is not set, it is automatically generated based on the table fields.
$row_info = $model->getListStructure($columns, 'id');
// Now $row_info is a ListStructure instance that can be modified
$row_info->setColumn('status', 'Status', 'select', false, false, ['0' => 'Draft', '1' => 'Active']);
setNoOrder()
Disables sorting for all table columns.
$model->setNoOrder();
setLimit($limit)
Sets the row limit per page.
$model->setLimit(20);
setOrder($order_field, $order_dir = 'desc')
Sets the default sorting order for the table. This defines which field and direction will be used for sorting when no user sorting is applied.
// Set default sorting by creation date, newest first
$model->setOrder('created_at', 'desc');
// Set default sorting by title, alphabetical order
$model->setOrder('title', 'asc');
// Set default sorting by ID, descending order (default direction)
$model->setOrder('id');
reorderColumns($db_names)
Reorders the columns of the table. This method supports method chaining.
$db_names can be a string or an array of strings. If it is a string it will insert the column at the first position, otherwise if it is an array it will reorder the array based on the specified order.
$listStructure->reorderColumns(['id', 'title']);
getTableStructure()
Returns the MySQL table structure.
$table_structure = $model->getTableStructure();
// Now $table_structure contains all the information about the table fields
setPrimaryKey($primary_key)
Manually sets the primary key of the table.
$model->setPrimaryKey('custom_id');
queryFromRequest($request = null)
Creates a query based on the request parameters (sorting, pagination).
// Standard usage with $_REQUEST
$query = $model->queryFromRequest();
// Usage with custom parameters
$query = $model->queryFromRequest([
'order_field' => 'id',
'order_dir' => 'desc',
'page' => 1,
'limit' => 20
]);
// Executing the query
$rows = Get::db()->getResults(...$query->get());
$total = Get::db()->getVar(...$query->getTotal());
getPageInfo($total)
Returns a PageInfo instance with pagination information.
// Get the total number of records
$total = Get::db()->getVar(...$query->getTotal());
// Get pagination information
$page_info = $model->getPageInfo($total);
// Now $page_info is a PageInfo instance that can be customized
$page_info->setPagination(true);
$page_info->setAjax(true);
$page_info->setId('my-table-id');
getDataChart($data, $structure)
Prepares data for display in a chart.
$query = $model->queryFromRequest();
$rows = Get::db()->getResults(...$query->get());
// Defining the chart structure
$chartStructure = [
'month' => ['label' => 'Month', 'axis' => 'x'],
'sales' => ['label' => 'Sales', 'type' => 'bar'],
'profit' => ['label' => 'Profit', 'type' => 'line', 'borderColor' => '#A02A4D']
];
// Preparing data for the chart
$chartData = $model->getDataChart($rows, $chartStructure);
2. ListStructure Class
The ListStructure class manages the column structure of a table. It implements the ArrayAccess, Iterator, and Countable interfaces to allow accessing properties as an array and iterating over them.
Public Functions of ListStructure
__construct(array $structure = [])
Constructor that can accept an initial structure array.
// Creates an empty structure
$listStructure = new App\Modellist\ListStructure();
// Creates with an initial structure
$listStructure = new App\Modellist\ListStructure([
'id' => ['type' => 'text', 'label' => 'ID', 'primary' => true],
'title' => ['type' => 'text', 'label' => 'Title']
]);
setColumn($db_name, $label, $type = 'text', $order = true, $primary = false, $options = [], $attributes_title = [], $attributes_data = [])
Sets or adds a column to the structure. This method supports method chaining.
// Adding basic columns
$listStructure->setColumn('id', 'ID', 'text', true, true)
->setColumn('title', 'Title', 'text', true, false);
// Column with 'select' type and options
$listStructure->setColumn(
'status', // Database field name
'Status', // Displayed label
'select', // Type
true, // Sortable
false, // Is not a primary key
['0' => 'Draft', '1' => 'Active'], // Options for select
['class' => 'bg-success'], // Header attributes
['class' => 'bg-danger'] // Data cell attributes
);
// Column of type 'action' with action definitions
$listStructure->setColumn(
'action',
'Actions',
'action',
false,
false,
['view' => 'View', 'edit' => 'Edit', 'delete' => 'Delete']
);
getColumn($db_name)
Gets a column from the structure.
$columnInfo = $listStructure->getColumn('status');
// $columnInfo contains all the column properties
deleteColumns($db_names)
Deletes a column from the structure. This method supports method chaining.
$listStructure->deleteColumns(['action', 'unnecessary_field']);
deleteColumn($db_name)
Deletes a column from the structure. This method supports method chaining.
$listStructure->deleteColumn('action')
->deleteColumn('unnecessary_field');
hideColumns($db_names)
Sets a column as hidden. This method supports method chaining.
$listStructure->hideColumns(['action', 'unnecessary_field']);
hideColumn($db_name)
Sets a column as hidden. This method supports method chaining.
$listStructure->hideColumn('action')
->hideColumn('unnecessary_field');
setAction($options = [], $label = 'Action')
Sets a column of type action. This method supports method chaining.
$listStructure->setAction(['edit' => 'Edit', 'delete' => 'Delete'], 'Actions');
setLabel($db_name, $label)
Sets the label of a column. This method supports method chaining.
$listStructure->setLabel('id', 'User ID')
->setLabel('title', 'Article Title');
setType($db_name, $type)
Sets the type of a column. This method supports method chaining.
$listStructure->setType('status', 'select')
->setType('created_at', 'date');
setOrder($db_name, $orderable)
Sets whether the column is sortable. This method supports method chaining.
$listStructure->setOrder('status', false)
->setOrder('title', true);
setPrimary($db_name)
Sets a column as the primary key. This method supports method chaining.
$listStructure->setPrimary('id');
setOptions($db_name, $options)
Sets the options for a select type column. This method supports method chaining.
$listStructure->setOptions('status', [
'0' => 'Draft',
'1' => 'In review',
'2' => 'Published'
]);
add_attribute_title($db_name, $attr_name, $attr_value)
Adds a single HTML attribute to a column's title. This method supports method chaining.
$listStructure->add_attribute_title('status', 'class', 'bg-primary')
->add_attribute_title('status', 'data-filter', 'status');
add_attribute_data($db_name, $attr_name, $attr_value)
Adds a single HTML attribute to a column's rows. This method supports method chaining.
$listStructure->add_attribute_data('status', 'class', 'text-center')
->add_attribute_data('title', 'data-toggle', 'tooltip');
getAttributesTitle($db_name)
Gets the HTML attributes of a column's title.
$attributes = $listStructure->getAttributesTitle('status');
// $attributes contains all the HTML attributes of the header
getAttributesData($db_name)
Gets the HTML attributes of a column's cells.
$attributes = $listStructure->getAttributesData('status');
// $attributes contains all the HTML attributes of the cells
disableAllOrder()
Disables sorting for all columns. This method supports method chaining.
$listStructure->disableAllOrder();
enableAllOrder()
Enables sorting for all columns. This method supports method chaining.
$listStructure->enableAllOrder();
toArray()
Converts the structure to an array.
$array = $listStructure->toArray();
// $array contains all the column definitions as an array
map(callable $callback)
Applies a callback function to each element of the structure. This method supports method chaining.
// Example: converts all labels to uppercase
$listStructure->map(function($row) {
$row['label'] = strtoupper($row['label']);
return $row;
});
3. PageInfo Class
The PageInfo class manages page information for the table. It implements the ArrayAccess, Iterator, and Countable interfaces to allow accessing properties as an array and iterating over them.
Public Functions of PageInfo
__construct(array $config = [])
Constructor that can accept an initial configuration array.
// Creates with default configuration
$pageInfo = new \App\PageInfo();
// Creates with custom configuration
$pageInfo = new \App\PageInfo([
'id' => 'my-table',
'limit' => 20,
'pagination' => true,
'ajax' => true
]);
setId($id)
Sets the table ID. This method supports method chaining.
$pageInfo->setId('my-custom-table');
setPage($page)
Sets the current page. This method supports method chaining.
$pageInfo->setPage('example_page');
setAction($action)
Sets the action. This method supports method chaining.
$pageInfo->setAction('custom_action');
setLimit($limit)
Sets the row limit per page. This method supports method chaining.
$pageInfo->setLimit(20);
setLimitStart($limitStart)
Sets the starting index for the limit. This method supports method chaining.
$pageInfo->setLimitStart(40);
setOrderField($field)
Sets the sorting field. This method supports method chaining.
$pageInfo->setOrderField('created_at');
setOrderDir($dir)
Sets the sorting direction. This method supports method chaining.
$pageInfo->setOrderDir('desc');
setTotalRecord($total)
Sets the total number of records. This method supports method chaining.
$pageInfo->setTotalRecord(150);
setFooter($enabled)
Enables/disables the footer. This method supports method chaining.
$pageInfo->setFooter(true);
setAjax($enabled)
Enables/disables ajax. This method supports method chaining.
$pageInfo->setAjax(true);
setPagination($enabled)
Abilita/disabilita la paginazione. Questo metodo supporta il method chaining.
$pageInfo->setPagination(true);
setBulkActions($actions)
Imposta le azioni bulk. Questo metodo supporta il method chaining.
$pageInfo->setBulkActions([
'delete' => 'Elimina selezionati',
'activate' => 'Attiva selezionati',
'deactivate' => 'Disattiva selezionati'
]);
addBulkAction($key, $label)
Aggiunge un'azione bulk. Questo metodo supporta il method chaining.
$pageInfo->addBulkAction('export', 'Esporta selezionati');
setAutoScroll($enabled)
Abilita/disabilita lo scrolling automatico. Questo metodo supporta il method chaining.
$pageInfo->setAutoScroll(false);
setPagTotalShow($enabled)
Abilita/disabilita la visualizzazione del totale nella paginazione. Questo metodo supporta il method chaining.
$pageInfo->setPagTotalShow(true);
setPagNumberShow($enabled)
Abilita/disabilita la visualizzazione dei numeri di pagina nella paginazione. Questo metodo supporta il method chaining.
$pageInfo->setPagNumberShow(true);
setPagGotoShow($enabled)
Abilita/disabilita la visualizzazione del selettore "vai alla pagina" nella paginazione. Questo metodo supporta il method chaining.
$pageInfo->setPagGotoShow(true);
setPagElPerPageShow($enabled)
Abilita/disabilita la visualizzazione del selettore "elementi per pagina" nella paginazione. Questo metodo supporta il method chaining.
$pageInfo->setPagElPerPageShow(true);
setPaginationLimit($limit)
Imposta il limite di pagine da mostrare nella paginazione. Questo metodo supporta il method chaining.
$pageInfo->setPaginationLimit(10);
setInputHidden($html)
Imposta il codice html da aggiungere alla fine dei campi hidden della form. Questo metodo supporta il method chaining.
$pageInfo->setInputHidden('');
setTableAttrs($key, $attrs)
Imposta gli attributi di una tabella. Questo metodo supporta il method chaining.
$pageInfo->setTableAttrs('table', ['class' => 'table table-hover js-table']);
toArray()
Converte le informazioni di pagina in un array.
$array = $pageInfo->toArray();
// $array contiene tutte le informazioni di paginazione come array
Complete examples
Basic table creation
$model = new \App\Modellist\ModelList('#__dynamic_example');
// Query construction based on request parameters
$query = $model->queryFromRequest();
// Data retrieval
$rows = Get::db()->getResults(...$query->get());
// Total count retrieval
$total = Get::db()->getVar(...$query->getTotal());
// Pagination configuration
$page_info = $model->getPageInfo($total);
// Table HTML generation
$table_html = Get::themePlugin('table', [
'info' => $model->getListStructure(),
'rows' => $rows,
'page_info' => $page_info
]);
// Output of the table
echo $table_html;
Table with footer and customizations
$model = new \App\Modellist\ModelList('#__dynamic_example');
$query = $model->queryFromRequest();
$rows = Get::db()->getResults(...$query->get());
$total = Get::db()->getVar(...$query->getTotal());
// Pagination configuration
$page_info = $model->getPageInfo($total);
$page_info->setId('my-table-id');
$page_info->setPagination(false);
// Enable the footer
$page_info->setFooter(true);
// Add line as footer
$rows[] = (object)['id' => '', 'title' => 'Totale', 'status' => '99999'];
// Table customization
$table_attrs = [
'tfoot' => ['class' => 'table-footer-gray'],
'tfoot.td.title' => ['class' => 'text-end']
];
// Table HTML generation
$table_html = Get::themePlugin('table', [
'info' => $model->getListStructure(),
'rows' => $rows,
'page_info' => $page_info,
'table_attrs' => $table_attrs
]);
// Output of the table
echo $table_html;
Table with custom structure and filters
$model = new \App\Modellist\ModelList('#__dynamic_example_2');
// Customizing the search filter
$model->addFilter('search', function($query, $search) use ($model) {
if ($search == 'draft') {
$query->where('`status` = 0');
} else if ($search == 'active') {
$query->where('`status` = 1');
} else {
// Cerca in tutte le colonne ad eccezione di status
$list_structure = $model->getTableStructure();
foreach ($list_structure as $field => $_) {
if ($field == 'status') continue;
$query->where('`'.$field.'` LIKE ? ', ['%'.$search.'%'], 'OR');
}
}
});
$query = $model->queryFromRequest();
$rows = Get::db()->getResults(...$query->get());
$rows = array_map(function($row) {
$row->content = substr($row->content, 0, 200) . '...';
return $row;
}, $rows);
// Customizing the table structure
$row_info = $model->getListStructure();
$row_info->setColumn(
'status', // Nome campo
'Status', // Etichetta
'select', // Tipo
false, // Non ordinabile
false, // Non è chiave primaria
['0' => 'Draft', '1' => 'Active'], // Opzioni per select
['class' => 'bg-success', 'data-customfilter' => 'status'], // Attributi intestazione
['class' => 'bg-danger'] // Attributi dati
)->setColumn(
'action', // Nome campo
'Action', // Etichetta
'action', // Tipo
false, // Non ordinabile
false, // Non è chiave primaria
['view' => 'View'] // Definizione azioni
);
// Change all labels to uppercase
$row_info->map(function($row) {
$row['label'] = strtoupper($row['label']);
return $row;
});
// Total record count
$total = Get::db()->getVar(...$query->getTotal());
// Pagination configuration
$page_info = $model->getPageInfo($total);
$page_info->setId('my-custom-table');
// Table customization
$table_attrs = [
'thead' => ['class' => 'table-header-yellow'],
'th.title' => ['class' => 'th-title']
];
// Table HTML generation
$table_html = Get::themePlugin('table', [
'info' => $row_info,
'rows' => $rows,
'page_info' => $page_info,
'table_attrs' => $table_attrs
]);
echo $table_html;
Multiple tables on the same page
function tableList() {
// First table
$id1 = _raz('table-dynamic-example');
if ((($_REQUEST['page-output'] ?? '') == 'json' && $_REQUEST['table_id'] == $id1) || ($_REQUEST['page-output'] ?? '') == '') {
$model = new \App\Modellist\ModelList('#__dynamic_example');
$query = $model->queryFromRequest();
$rows1 = Get::db()->getResults(...$query->get());
// Calculate the query columns before executing another query (total)
$columns = $this->model->getQueryColumns();
$total1 = Get::db()->getVar(...$query->getTotal());
$page_info1 = $model->getPageInfo($total1);
$page_info1->setId($id1);
$page_info1->setPagination(false);
$page_info1->setFooter(true);
$table_attrs1 = [
'tfoot' => ['class' => 'table-footer-gray'],
'tfoot.td.title' => ['class' => 'text-end']
];
$rows1[] = (object)['id' => '', 'title' => 'Total', 'status' => '99999'];
$table_html1 = Get::themePlugin('table', [
'info' => $model->getListStructure(array_keys($rows1[0]), 'id'),
'rows' => $rows1,
'page_info' => $page_info1,
'table_attrs' => $table_attrs1
]);
}
// Second table
$id2 = _raz('table-dynamic-example-2');
if ((($_REQUEST['page-output'] ?? '') == 'json' && $_REQUEST['table_id'] == $id2) || ($_REQUEST['page-output'] ?? '') == '') {
$model2 = new \App\Modellist\ModelList('#__dynamic_example_2');
// Customizing the search filter
$model2->addFilter('search', function($query, $search) use ($model2) {
if ($search == 'draft') {
$query->where('`status` = 0');
} else if ($search == 'active') {
$query->where('`status` = 1');
} else {
// Cerca in tutte le colonne tranne status
$list_structure = $model2->getTableStructure();
foreach ($list_structure as $field => $_) {
if ($field == 'status') continue;
$query->where('`'.$field.'` LIKE ? ', ['%'.$search.'%'], 'OR');
}
}
});
$query2 = $model2->queryFromRequest();
$rows2 = Get::db()->getResults(...$query2->get());
// Modify a column of the array
$rows2 = array_map(function($row) {
$row->content = substr($row->content, 0, 200) . '...';
return $row;
}, $rows2);
// Customizing the table structure
$row_info = $model2->getListStructure();
$row_info->setColumn(
'status',
'Status',
'select',
false,
false,
['0' => 'Draft', '1' => 'Active'],
['class' => 'bg-success', 'data-customfilter' => 'status'],
['class' => 'bg-danger']
)->setColumn(
'action',
'Action',
'action',
false,
false,
[$id2.'-view' => 'View']
);
$row_info->map(function($row) {
$row['label'] = strtoupper($row['label']);
return $row;
});
$total2 = Get::db()->getVar(...$query2->getTotal());
$page_info2 = $model2->getPageInfo($total2);
$page_info2->setId($id2);
// Table customization
$table_attrs2 = [
'thead' => ['class' => 'table-header-yellow'],
'th.title' => ['class' => 'th-title']
];
// Table HTML generation
$table_html2 = Get::themePlugin('table', [
'info' => $row_info,
'rows' => $rows2,
'page_info' => $page_info2,
'table_attrs' => $table_attrs2
]);
}
// Output management
if (($_REQUEST['page-output'] ?? '') == 'json') {
// Update one of the two tables
if ($_REQUEST['table_id'] == $id2) {
Response::themePage('json', '', json_encode([
'html' => $table_html2,
'success' => 'true',
'msg' => ''
]));
} else if ($_REQUEST['table_id'] == $id1) {
Response::themePage('json', '', json_encode([
'html' => $table_html1,
'success' => 'true',
'msg' => ''
]));
}
} else {
// Complete page rendering with both tables
Response::themePage('default', __DIR__ . '/table.page.php', [
'table_html1' => $table_html1,
'table_html2' => $table_html2,
'table_id2' => $id2,
'row_info' => $row_info,
'page_info' => $page_info2
]);
}
}