tobento/service-table

Building HTML tables easily.

1.0.3 2024-06-05 06:05 UTC

This package is auto-updated.

Last update: 2025-02-05 07:30:25 UTC


README

The Table Service provides a way for building tables easily.

Table of Contents

Getting started

Add the latest version of the Table service project running this command.

composer require tobento/service-table

Requirements

  • PHP 8.0 or greater

Highlights

  • Framework-agnostic, will work with any project
  • Decoupled design
  • Customize rendering

Screenshots


Simple Example

use Tobento\Service\Table\Table;

$table = new Table('products');

$table->row([
    'sku' => 'Sku',
    'title' => 'Title',
    'description' => 'Description',
    'price' => 'Price',
])->heading();

$table->row([
    'sku' => 'shirt',
    'title' => 'Shirt',
    'description' => 'A nice shirt in blue color.',
    'price' => 19.99,
]);

Render the table

<?= $table->render() ?>

// or just
<?= $table ?>

Both tables from above will produce the following output

<div class="table">
    <div class="table-row th">
        <div class="table-col grow-1">Sku</div>
        <div class="table-col grow-1">Title</div>
        <div class="table-col grow-2">Description</div>
        <div class="table-col grow-1">Price</div>
    </div>
    <div class="table-row">
        <div class="table-col grow-1">shirt</div>
        <div class="table-col grow-1">Shirt</div>
        <div class="table-col grow-2">A nice shirt in blue color.</div>
        <div class="table-col grow-1">19.99</div>
    </div>
</div>

Documentation

Create Table

use Tobento\Service\Table\Table;
use Tobento\Service\Table\TableInterface;
use Tobento\Service\Table\Renderer;

$table = new Table(
    name: 'products',
    columns: ['title', 'description'], // The columns to render only.
    renderer: new Renderer(),
);

var_dump($table instanceof TableInterface);
// bool(true)

// Get the name of the table:
var_dump($table->name());
// string(8) "products"

With Methods

You might change some data or implentation by the following "with methods" returning a new instance.

withColumns

use Tobento\Service\Table\Table;

$table = new Table('products');

$newTable = $table->withColumns(['sku', 'title']);

var_dump($table === $newTable);
// bool(false)

withRenderer

use Tobento\Service\Table\Table;
use Tobento\Service\Table\Renderer;

$table = new Table('products');

$newTable = $table->withRenderer(new Renderer());

var_dump($table === $newTable);
// bool(false)

Create Rows

Creating rows from array items

use Tobento\Service\Table\Table;

$table = new Table('products');

$table->rows([
    [
        'sku' => 'shirt',
        'title' => 'Shirt',
        'description' => 'A nice shirt in blue color.',
        'price' => 19.99,
    ],
    [
        'sku' => 'cap',
        'title' => 'Cap',
        'description' => 'A nice cap.',
        'price' => 11.99,
    ],    
]);

Using a callback for creating rows

You may use a callback for creating rows if you provide an array of objects for instance or want to create only specific row columns.

use Tobento\Service\Table\Table;
use Tobento\Service\Table\Row;

class Product
{
    public function __construct(
        protected string $title,
        protected float $price,
    ) {}

    public function title(): string
    {
        return $this->title;
    }
    
    public function price(): float
    {
        return $this->price;
    }         
}

$table = new Table('products');

$table->rows([
    new Product('Shirt', 19.99),
    new Product('Cap', 11.99),  
], function(Row $row, Product $product): void {
    $row->column(key: 'title', text: $product->title());
    $row->column(key: 'price', text: $product->price(), attributes: ['data-foo' => 'value']);
});

Create only specific row columns from an array of items:

$table = new Table('products');

$table->rows([
    [
        'sku' => 'shirt',
        'title' => 'Shirt',
        'description' => 'A nice shirt in blue color.',
        'price' => 19.99,
    ],
    [
        'sku' => 'cap',
        'title' => 'Cap',
        'description' => 'A nice cap.',
        'price' => 11.99,
    ],
], function(Row $row, array $item): void {
    $row->column(key: 'title', text: $item['title']);
    $row->column(key: 'price', text: $item['price'], attributes: ['data-foo' => 'value']);
});

Create Row

Creating a row from an array

use Tobento\Service\Table\Table;

$table = new Table('products');

$table->row([
    'sku' => 'shirt',
    'title' => 'Shirt',
    'description' => 'A nice shirt in blue color.',
    'price' => 19.99,
]);

Using a callback for creating row columns

You may use a callback for creating row columns if you provide an object.

use Tobento\Service\Table\Table;
use Tobento\Service\Table\Row;

class Product
{
    public function __construct(
        protected string $title,
        protected float $price,
    ) {}

    public function title(): string
    {
        return $this->title;
    }
    
    public function price(): float
    {
        return $this->price;
    }         
}

$table = new Table('products');

$table->row(
    new Product('Shirt', 19.99),
    function(Row $row, Product $product): void {
        $row->column(key: 'title', text: $product->title())
            ->column(key: 'price', text: $product->price(), attributes: ['data-foo' => 'value']);
    }
);

Row Methods

Heading

You may mark the row as a heading.

use Tobento\Service\Table\Table;

$table = new Table('products');

$table->row([
    'title' => 'Title',
    'description' => 'Description',
])->heading();

Id

You may give the row an id to fetch it later.

use Tobento\Service\Table\Table;

$table = new Table('products');

$table->row([
    'title' => 'Title',
    'description' => 'Description',
])->id('header');

$headerRow = $table->getRow('header');

Each

You may use the each method to create the row columns.

use Tobento\Service\Table\Table;
use Tobento\Service\Table\Row;

$item = [
    'sku' => 'shirt',
    'title' => 'Shirt',
    'description' => 'A nice shirt in blue color.',
    'price' => 19.99,
];

$table = new Table('products');

$table->row()
      ->each($item, function(Row $row, $value, $key): void {
            $row->column(key: $key, value: $value);
      });

When

The when method will execute the given callback when the first argument given to the method evaluates to true.

use Tobento\Service\Table\Table;
use Tobento\Service\Table\Row;

$table = new Table('products');

$table->row()
      ->when(true, function(Row $row): void {
          $row->column('actions', 'Actions');
      });

Html

You may mark columns as html, indicating that no escaping is done.

use Tobento\Service\Table\Table;

$table = new Table('products');

$table->row([
    'sku' => 'shirt',
    'title' => 'Shirt',
    'description' => '<p>A nice shirt in blue color.</p>',
    'price' => 19.99,
])->html('description');

PependHtml / AppendHtml

You may prepend and append html to the row.

use Tobento\Service\Table\Table;

$table = new Table('products');

$table->row([
    'sku' => '<input type="text" id="sku" name="sku">',
    'title' => '<input type="text" id="title" name="title">',
])->html('sku')
  ->html('title')
  ->prependHtml('<form>')
  ->appendHtml('</form>');

Column

You may use the column method to add a column.

use Tobento\Service\Table\Table;

$table = new Table('products');

$table->row()
      ->column(key: 'sku', text: 'Sku')
      ->column(key: 'title', text: 'Title', attributes: ['data-foo' => 'Foo']);

Custom Row

You may use the addRow method to pass a custom row.

use Tobento\Service\Table\Table;
use Tobento\Service\Table\RowInterface;

$table = new Table('products');

// must implement RowInterface
$customRow = new CustomRow();

$table->addRow($customRow);

Table Attributes

You may set table attributes which will be rendered depending on the renderer.

use Tobento\Service\Table\Table;

$table = new Table('products');
$table->attributes(['data-foo' => 'value']);

$attributes = $table->getAttributes();
// ['data-foo' => 'value']

Render Table

There are different ways of rendering the table depending on your needs.

Default Renderer

The default renderer generates the table using <div> elements and calculates the columns size automatically.

use Tobento\Service\Table\Table;
use Tobento\Service\Table\Renderer;

$table = new Table(
    name: 'products',
    renderer: new Renderer(),
);

$table->attributes(['data-id' => 'value']);

$table->row([
    'sku' => 'Sku',
    'title' => 'Title',
    'description' => 'Description',
    'price' => 'Price',
])->heading();

$table->row([
    'sku' => 'shirt',
    'title' => 'Shirt',
    'description' => 'A nice shirt in blue color.',
    'price' => 19.99,
])->attributes(['data-row' => 'name']);

echo $table;

Outputs:

<div class="table" data-id="value">
    <div class="table-row th">
        <div class="table-col grow-1">Sku</div>
        <div class="table-col grow-1">Title</div>
        <div class="table-col grow-2">Description</div>
        <div class="table-col grow-1">Price</div>
    </div>
    <div class="table-row" data-row="name">
        <div class="table-col grow-1">shirt</div>
        <div class="table-col grow-1">Shirt</div>
        <div class="table-col grow-2">A nice shirt in blue color.</div>
        <div class="table-col grow-1">19.99</div>
    </div>
</div>

Table Renderer

The table renderer generates the table using the <table> HTML element.

use Tobento\Service\Table\Table;
use Tobento\Service\Table\TableRenderer;

$table = new Table(
    name: 'products',
    renderer: new TableRenderer(),
);

$table->attributes(['data-id' => 'value']);

$table->row([
    'sku' => 'Sku',
    'title' => 'Title',
    'description' => 'Description',
    'price' => 'Price',
])->heading();

$table->row([
    'sku' => 'shirt',
    'title' => 'Shirt',
    'description' => 'A nice shirt in blue color.',
    'price' => 19.99,
])->attributes(['data-row' => 'name']);

echo $table;

Outputs:

<table data-id="value">
    <tr>
        <th>Sku</th>
        <th>Title</th>
        <th>Description</th>
        <th>Price</th>
    </tr>
    <tr data-row="name">
        <td>shirt</td>
        <td>Shirt</td>
        <td>A nice shirt in blue color.</td>
        <td>19.99</td>
    </tr>
</table>

The $table->row()->prependHtml() and $table->row()->appendHtml methods will be ignored as it would produce invalid HTML!

Custom Renderer

You might write your own renderer fitting your application.

use Tobento\Service\Table\RendererInterface;
use Tobento\Service\Table\TableInterface;

class CustomRenderer implements RendererInterface
{
    /**
     * Render the table.
     *
     * @param TableInterface $table
     * @return string
     */
    public function render(TableInterface $table): string
    {
        // create the your custom table ...
        
        return 'table';
    }
}

Credits