# Table inheritance

> Extend table definitions and apply per-page overrides.

Source: https://docs.inertiax.dev/table/guide/table-inheritance/

A child table declares only the columns or filters it adds or replaces:

```php
namespace App\Tables;

use InertiaX\Table\Columns\TextColumn;

class DirectoryTable extends UsersTable
{
    protected function columns(): array
    {
        return [
            TextColumn::make('email', 'Work email')->copyable()->searchable(),
        ];
    }
}
```

This extends the [UsersTable example](https://docs.inertiax.dev/table/guide/tables/) and replaces its email column. InertiaX composes declarations from base to child; do not call `parent::columns()` or `parent::filters()`.

## Precedence

Class declarations compose from the oldest base class to the concrete class. A child definition with the same key replaces the inherited definition without moving its position. Per-use fluent operations then run in call order.

Protected static defaults inherit too. The nearest initialized subclass value wins, followed by any fluent override. Explicit column options override table-wide column defaults.

Use `$defaultFilterMode`, `$defaultPageSize`, and the other [documented defaults](https://docs.inertiax.dev/table/reference/defaults/) for class options.

A fluent `data()` value takes precedence over class `data()` declarations. Among class declarations, the most derived result wins.

## Change one instance

```php
DirectoryTable::make('directory')
    ->data($users)
    ->removeColumn('email')
    ->pageSize(50);
```

Use `addColumn()` for a new key and `replaceColumn()` for an existing key. Duplicate adds and missing replacements or removals fail. The same rules apply to filters and filter clauses.

`setColumns()` and `setFilters()` clear the collection, then add the supplied definitions. Keep the row-key column when replacing a whole column list. With `autoColumns()` enabled, inference still adds eligible model fields after explicit operations; disable it for a fully explicit list.

See [Table API](https://docs.inertiax.dev/table/reference/table/#definition-operations) for the operation list and [Defaults](https://docs.inertiax.dev/table/reference/defaults/) for subclass properties.

## Module contributions

Use static registration when a module contributes definitions to a table class and its descendants. Register during application boot, before any table executes:

```php
UsersTable::registerColumn(
    TextColumn::make('department'),
    name: 'directory-department',
);
```

Ordinary registrations precede class declarations. Explicit registered replacements run after class declarations, and per-use fluent operations run last. Registration order and priority determine ordering within a scope. The catalog freezes on its first execution read; later changes fail. Do not capture request-specific objects in boot-time registrations.

For a definition owned by one table, prefer its `columns()` or `filters()` method. Registration methods and inspection are listed in [Table API](https://docs.inertiax.dev/table/reference/table/#module-registrations).

## Custom builders

Declare both sides of the relationship when a Table uses a custom builder:

```php
use App\Models\User;
use InertiaX\Table\Table;
use InertiaX\Table\TableBuilder;

/** @extends Table<UsersTableBuilder> */
class UsersTable extends Table
{
    protected static string $builder = UsersTableBuilder::class;
}

/** @extends TableBuilder<UsersTable> */
class UsersTableBuilder extends TableBuilder
{
    public function compact(): static
    {
        return $this->pageSize(10);
    }
}

UsersTable::make('users')->compact()->data(User::query());
```

The factory returns `UsersTableBuilder`; materialization returns `UsersTable`. The same `@extends` pattern applies to custom Column and Filter classes and their builders. Ordinary Table subclasses using the standard builder need no annotation to access its fluent methods.
