An object-oriented HTML table generator simplified in PHP.
A simple HTML table generator in PHP.
Install the package using Composer:
$ composer require rougin/gableThe 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>alpinejsFor 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)<tr> element to the <thead>.newRow($class = null, $style = null, $width = null)<tr> element to the <tbody>.setCell($value, $align = null, $class = null, $cspan = null, $rspan = null, $style = null, $width = null)<td> element.withActions($value = 'Action', ...)withAlpine($name = 'items', ...)withDeleteAction($clicked, $name = 'Delete')Delete action.withLoading($count = 5, $name = 'loading')withUpdateAction($clicked, $name = 'Update')Update action.withNoItemsText($text, $key = 'empty')withLoadErrorText($text, $key = 'loadError')