Key concepts overview

What ApiTables is, why it exists, and how the pieces fit together

If you are new to the team, read this page before writing any table code. It explains the idea behind ApiTables so the rest of the docs make sense.

What problem does ApiTables solve?

Most admin panels need data tables: sortable columns, filters, pagination, row buttons (“Edit”, “Delete”), and bulk actions (“Export selected”). Without a shared approach, every feature team rebuilds the same UI and API contract from scratch.

ApiTables splits the work cleanly:

WhoResponsibility
Backend (you)Define what the table shows, how data is queried, and what actions are allowed
FrontendRender the table from JSON — no hard-coded columns or buttons

This is called server-driven UI: the server sends structure; the client renders it.

Analogy

Think of a table class as a recipe card. The frontend is the kitchen — it follows the recipe but does not invent ingredients. If you forget to list an action in setRowActions(), the button will not appear, no matter what the frontend team does.

The three phases of every table

Every ApiTables feature goes through the same lifecycle:

Phase 1 — Structure (GET)

The client asks: “What columns, filters, and actions exist for table users?”

You answer via load-table/users. The response is JSON metadata — not the full dataset (unless withData=true).

Phase 2 — Data (POST)

The client asks: “Give me page 2 of users where name contains ‘john’, sorted by created_at.”

You answer via query-table/users. The package applies filters and sorting on your Eloquent builder and returns paginated rows.

Phase 3 — Actions (POST)

The user clicks “Archive” on a row or “Export” in the toolbar.

The client POSTs to the action URL that was embedded in the structure response. Your table class runs the callback and returns success/errors.

What you actually write as a backend developer

You rarely touch the package internals. Day-to-day work is:

  1. One config entry per table in api-tables-config.php
  2. One PHP class per table extending TableAbstract
  3. Optional translation keys, export views, and custom middleware
config/api-tables-config.php     ← registry (table name → model + class)
app/ApiTables/UsersTable.php     ← your table definition
lang/en/api-table.php            ← column labels (optional)

The package handles routing, JSON shaping, pagination, and default actions (show details, export Excel).

How this connects to the frontend

The React ApiTables module in our apps:

  1. Calls load-table/{name} on page load
  2. Stores structure in Redux
  3. Calls query-table/{name} when the user changes page, filter, or sort
  4. POSTs to action URLs when the user clicks buttons

Both sides must agree on field names. The contract is documented in Table structure. When in doubt, log the load-table response and compare with the frontend docs.

Junior vs senior mental model

LevelFocus on
JuniorConfig registration, $TBLColumns, basic filters, testing with curl/Postman
MidRow/bulk actions, bindings, scoped queries via params, middleware per table
SeniorCustom exports, email report pipeline, performance (eager loading, indexes), extending GeneralExport

Common misconceptions

MisconceptionReality
“I need to build REST endpoints for each column”No — one load-table + one query-table per table name
“The frontend team adds filters”Filters are defined in your filters() method
“Table name can be anything in the URL”URL segment must match a key in config('api-tables-config.tables')
“Actions are separate Laravel routes I register”Action URLs are generated automatically from your TableRowAction / TableBulkAction definitions

Next steps

Your goalRead next
Install and ship first tableGetting started
Understand request flowData flow
Look up a termGlossary
Something brokeTroubleshooting

On this page