A simple HTML table generator in PHP.
Install the package using Composer:
$ composer require rougin/gable
The Table
class is the cornerstone of this package, providing a simple and intuitive API for generating HTML tables:
// index.php
use Rougin\Gable\Table;
$table = new Table;
// Define the table columns ---
$table->newColumn();
$table->setCell('Name');
$table->setCell('Age');
// ----------------------------
// Populate the table with data ---
$table->newRow();
$table->setCell('John Doe');
$table->setCell('30');
$table->newRow();
$table->setCell('Jane Doe');
$table->setCell('28');
// --------------------------------
// Use the "__toString" method ---
echo $table;
// -------------------------------
The code above will generate the following HTML output:
<table>
<thead>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<tr>
<td>John Doe</td>
<td>30</td>
</tr>
<tr>
<td>Jane Doe</td>
<td>28</td>
</tr>
</tbody>
</table>
For a more fluent and expressive way of building tables, method chaining is also supported:
// index.php
use Rougin\Gable\Table;
$table = new Table;
echo $table->newColumn()
->setCell('Name')
->setCell('Age')
->newRow()
->setCell('John Doe')
->setCell('30')
->newRow()
->setCell('Jane Doe')
->setCell('28');
The appearance of the table can be customized by adding CSS classes, inline styles, and other attributes to columns, rows, and cells:
// index.php
use Rougin\Gable\Table;
$table = new Table;
// Adds CSS classes to the <table> element ---
$table->setClass('table table-striped');
// ------------------------------------------
// Adds a CSS class to the <thead> row ---
$table->newColumn('fw-bold');
// --------------------------------------
// Aligns to center then adds a CSS class to the cell ---
$table->setCell('Name', 'center', 'text-uppercase');
// ------------------------------------------------------
// Aligns cell to the right ----
$table->setCell('Age', 'right');
// -----------------------------
// Adds a CSS class to the <tr> element ---
$table->newRow('table-primary');
// ----------------------------------------
$table->setCell('John Doe');
$table->setCell('30');
$table->newRow();
// Adds a CSS class to the current cell --------
$table->setCell('Jane Doe', null, 'fst-italic');
// ---------------------------------------------
$table->setCell('28');
echo $table;
<table class="table table-striped">
<thead>
<tr class="fw-bold">
<th align="center" class="text-uppercase">Name</th>
<th align="right">Age</th>
</tr>
</thead>
<tbody>
<tr class="table-primary">
<td>John Doe</td>
<td>30</td>
</tr>
<tr>
<td class="fst-italic">Jane Doe</td>
<td>28</td>
</tr>
</tbody>
</table>
Actions can be added to each row, allowing for operations like updating or deleting records. The withUpdateAction
and withDeleteAction
methods provide a convenient way to add the specified common actions:
// index.php
use Rougin\Gable\Table;
$table = new Table;
$table->newColumn();
$table->setCell('Name');
$table->setCell('Age');
// Adds an "Action" column ---
$table->withActions();
// ---------------------------
// Assumes "alpinejs" is integrated --------
$table->withUpdateAction('update(item.id)');
$table->withDeleteAction('delete(item.id)');
// -----------------------------------------
$table->newRow();
$table->setCell('John Doe');
$table->setCell('30');
$table->newRow();
$table->setCell('Jane Doe');
$table->setCell('28');
echo $table;
<table>
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr>
<td>John Doe</td>
<td>30</td>
<td>
<div class="dropdown">
<button class="btn btn-primary btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown">Action</button>
<div class="dropdown-menu dropdown-menu-end">
<div><a class="dropdown-item" href="javascript:void(0)" @click="update(item.id)">Update</a></div>
<div><hr class="dropdown-divider"></div>
<div><a class="dropdown-item text-danger" href="javascript:void(0)" @click="delete(item.id)">Delete</a></div>
</div>
</div>
</td>
</tr>
<tr>
<td>Jane Doe</td>
<td>28</td>
<td>
<div class="dropdown">
<button class="btn btn-primary btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown">Action</button>
<div class="dropdown-menu dropdown-menu-end">
<div><a class="dropdown-item" href="javascript:void(0)" @click="update(item.id)">Update</a></div>
<div><hr class="dropdown-divider"></div>
<div><a class="dropdown-item text-danger" href="javascript:void(0)" @click="delete(item.id)">Delete</a></div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
Note
This is only works when integrated in alpinejs
.
Badges can be used to highlight certain information in a cell, such as a record's status.
// index.php
use Rougin\Gable\Table;
$table = new Table;
$table->newColumn();
$table->setCell('Status')
->addBadge('Active', "item.status === 'active'", 'bg-success')
->addBadge('Inactive', "item.status === 'inactive'", 'bg-danger');
$table->setCell('Name');
$table->newRow();
// Placeholder for the badge ---
$table->setCell('');
// -----------------------------
$table->setCell('John Doe');
echo $table;
<table>
<thead>
<tr>
<th>Name</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>John Doe</td>
<td>
<template x-if="item.status === 'active'">
<span class="badge rounded-pill text-uppercase bg-success">Active</span>
</template>
<template x-if="item.status === 'inactive'">
<span class="badge rounded-pill text-uppercase bg-danger">Inactive</span>
</template>
</td>
</tr>
</tbody>
</table>
Note
This is only works when integrated in alpinejs
.
The Pagee
class provides a simple way to generate pagination links for a table:
// index.php
use Rougin\Gable\Pagee;
$pagee = new Pagee;
$pagee->setTotal(100); // Total number of items
$pagee->setLimit(10); // Items per page
$pagee->setPage(2); // Current page
$pagee->setLink('/users'); // Base URL for the links
echo $pagee;
<div class="d-inline-block">
<ul class="pagination">
<li class="page-item">
<a class="page-link" href="/users?p=1&l=10">
<span>First</span>
</a>
</li>
<li class="page-item">
<a class="page-link" href="/users?p=1&l=10">
<span>Previous</span>
</a>
</li>
<li class="page-item">
<a class="page-link" href="/users?p=1&l=10">
<span>1</span>
</a>
</li>
<li class="page-item active">
<a class="page-link" href="javascript:void(0)">
<span>2</span>
</a>
</li>
<li class="page-item">
<a class="page-link" href="/users?p=3&l=10">
<span>3</span>
</a>
</li>
<li class="page-item">
<a class="page-link" href="/users?p=4&l=10">
<span>4</span>
</a>
</li>
<li class="page-item">
<a class="page-link" href="/users?p=5&l=10">
<span>5</span>
</a>
</li>
<li class="page-item">
<a class="page-link" href="/users?p=6&l=10">
<span>6</span>
</a>
</li>
<li class="page-item">
<a class="page-link" href="/users?p=7&l=10">
<span>7</span>
</a>
</li>
<li class="page-item">
<a class="page-link" href="/users?p=8&l=10">
<span>8</span>
</a>
</li>
<li class="page-item">
<a class="page-link" href="/users?p=9&l=10">
<span>9</span>
</a>
</li>
<li class="page-item">
<a class="page-link" href="/users?p=10&l=10">
<span>10</span>
</a>
</li>
<li class="page-item">
<a class="page-link" href="/users?p=3&l=10">
<span>Next</span>
</a>
</li>
<li class="page-item">
<a class="page-link" href="/users?p=10&l=10">
<span>Last</span>
</a>
</li>
</ul>
</div>
For creating dynamic and interactive tables, Gable
provides a seamless integration with alpinejs. This allows for features like real-time data updates, loading indicators, and more:
// index.php
use Rougin\Gable\Table;
$table = new Table;
// Sets the table with "users" for "alpinejs" ---
$table->withAlpine('users');
// ----------------------------------------------
// Shows a loading indicator while data is being fetched ---
$table->withLoading();
// ---------------------------------------------------------
$table->newColumn();
$table->setCell('Name')->withName('name');
$table->setCell('Email')->withName('email');
echo $table;
This will generate a table that is bound to an alpinejs
component, ready to display dynamic data:
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<template x-if="items.length === 0 && loading">
<template x-data="{ length: items && items.length ? items.length : 5 }" x-for="i in length">
<tr>
<td class="align-middle placeholder-glow"><span class="placeholder col-12"></span></td>
<td class="align-middle placeholder-glow"><span class="placeholder col-12"></span></td>
</tr>
</template>
</template>
<template x-if="items.length === 0 && empty">
<tr>
<td colspan="2" class="align-middle text-center"><span>No items found.</span></td>
</tr>
</template>
<template x-if="! loading && loadError">
<tr>
<td colspan="2" class="align-middle text-center"><span>An error occured in getting the items.</span></td>
</tr>
</template>
<template x-if="items && items.length > 0">
<template x-for="item in users">
<tr>
<td x-text="item.name"></td>
<td x-text="item.email"></td>
</tr>
</template>
</template>
</tbody>
</table>
The following methods are available in the Table
class for advanced customization:
newColumn($class = null, $style = null, $width = null)
- Adds a new
<tr>
element to the<thead>
.
newRow($class = null, $style = null, $width = null)
- Adds a new
<tr>
element to the<tbody>
.
setCell($value, $align = null, $class = null, $cspan = null, $rspan = null, $style = null, $width = null)
- Adds a new
<td>
element.
withActions($value = 'Action', ...)
- Adds a column for actions.
withAlpine($name = 'items', ...)
- Integrates the table with Alpine.js.
withDeleteAction($clicked, $name = 'Delete')
- Adds a
Delete
action.
withLoading($count = 5, $name = 'loading')
- Adds a loading indicator.
withUpdateAction($clicked, $name = 'Update')
- Adds an
Update
action.
withNoItemsText($text, $key = 'empty')
- Sets the text to display when there are no items in the table.
withLoadErrorText($text, $key = 'loadError')
- Sets the text to display when an error occurs while loading items.
See CHANGELOG for more recent changes.
Includes tools for code quality, coding style, and unit tests.
Analyze code quality using phpstan:
$ phpstan
Enforce coding style using php-cs-fixer:
$ php-cs-fixer fix --config=phpstyle.php
Execute unit tests using phpunit:
$ composer test