rougin/gable

A simple HTML table generator in PHP.

dev-master 2025-08-24 08:35 UTC

This package is auto-updated.

Last update: 2025-08-24 08:35:26 UTC


README

A simple HTML table generator in PHP.

Installation

Install the package using Composer:

$ composer require rougin/gable

Basic usage

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>

Method chaining

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');

Customization

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

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

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.

Pagination

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>

Integration to alpinejs

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>

Available methods

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.

Change log

See CHANGELOG for more recent changes.

Development

Includes tools for code quality, coding style, and unit tests.

Code quality

Analyze code quality using phpstan:

$ phpstan

Coding style

Enforce coding style using php-cs-fixer:

$ php-cs-fixer fix --config=phpstyle.php

Unit tests

Execute unit tests using phpunit:

$ composer test