Skip to content

Table Classes

Every table extends Forjed\InertiaTable\Table and implements one required method: columns().

Creating a Table

php
use Forjed\InertiaTable\Table;
use Forjed\InertiaTable\Column;

class ServerTable extends Table
{
    protected function columns(): array
    {
        return [
            Column::make('name', 'Name')->sortable()->text(),
            Column::make('ip', 'IP Address')->sortable(),
            Column::data('id'),
        ];
    }
}

Properties

PropertyTypeDefaultDescription
$defaultSortstring'-created_at'Default sort column. Prefix with - for descending
$perPageint10 (from config)Rows per page
$identifier?stringnullScopes all URL params (search, sort, page) - see Identifier
$tableSettingsarray[]Extension metadata for the frontend

Instantiation

The constructor accepts Eloquent\Builder, Query\Builder, or Relation instances:

php
// Static factory (recommended)
ServerTable::make(Server::query());

// With scopes
ServerTable::make(Server::where('active', true));

// With relations
ServerTable::make($project->servers());

Fluent Setters

php
ServerTable::make(Server::query())
    ->perPage(25)
    ->identifier('servers')             // scopes URL params for multi-table pages
    ->withSettings(['key' => 'value'])  // extension metadata
    ->paginate();

Identifier

When you have multiple tables on the same page, use identifier() to scope each table's URL parameters. Without an identifier, tables share search, sort, and page params - causing conflicts.

php
// Table 1 - uses ?serversSearch=, ?serversSort=, ?serversPage=
ServerTable::make(Server::query())
    ->identifier('servers')
    ->paginate();

// Table 2 - uses ?sitesSearch=, ?sitesSort=, ?sitesPage=
SiteTable::make(Site::query())
    ->identifier('sites')
    ->paginate();
IdentifierSearch paramSort paramPage param
null (default)searchsortpage
'servers'serversSearchserversSortserversPage
'sites'sitesSearchsitesSortsitesPage

You can also set it as a class property:

php
class ServerTable extends Table
{
    protected ?string $identifier = 'servers';
}

The identifier is passed to the frontend automatically - no additional React/Vue configuration needed.

Output Methods

For Inertia (paginated response)

MethodDescription
->paginate()Full pagination - includes total count and last_page
->simplePaginate()Simple pagination - no COUNT(*) query, faster
php
// In your controller
return Inertia::render('Servers', [
    'servers' => ServerTable::make(Server::query())->paginate(),
]);

For raw data (no pagination)

MethodDescription
->toArray()All matching rows as a flat array
->toCollection()All matching rows as a Laravel Collection

Both apply search and sorting but skip pagination. Optional take and skip parameters for chunking:

php
// All rows
$rows = ServerTable::make(Server::query())->toArray();

// As a Collection
$rows = ServerTable::make(Server::query())->toCollection();

// With take/skip
$chunk = ServerTable::make(Server::query())->toArray(take: 100, skip: 200);

Response Shape

paginate() and simplePaginate() return an array with these keys:

KeyTypeDescription
columnsarrayColumn definitions for the frontend
dataarrayRow data (including hidden columns)
linksarrayPagination URLs (first, last, prev, next)
metaarrayPagination metadata (current_page, from, to, per_page, etc.)
searchableboolWhether the table has searchable fields
searchDebounceintDebounce time in ms (from config)
dateFormatstringPHP date format string (from config) - used for server-side formatting
identifierstring|nullTable identifier for scoped URL params
tableSettingsarrayExtension metadata for the frontend

Default Query Modifications

Override query() to apply default query modifications - eager loading, scopes, joins, or anything else - without touching the constructor:

php
class ServerTable extends Table
{
    protected function query(): void
    {
        $this->query->with(['owner', 'tags']);
        $this->query->where('archived', false);
    }
}

The query() method runs at the start of every query, before columns are resolved, hooks are executed, and search/sorting are applied:

1. query()                            <-- your default modifications
2. $columns = $this->columns()
3. Global beforeQuery hooks
4. Class-specific beforeQuery hooks
5. applySearch()
6. applySorting($columns)
7. ...

This is different from Table Hooks, which modify tables from the outside (service providers, packages). The query() method is for modifications that are intrinsic to the table class itself.

Searchable Fields

Override searchable() to enable global search:

php
protected function searchable(): array
{
    return ['name', 'ip', 'hostname'];
}

Return [] (the default) to disable search.