Guards and middleware

Route prefixes, auth guards, and per-table middleware

Guards and middleware control who can hit your table endpoints and under which URL prefix. This is essential for security reviews and debugging 401/403 errors.

Guards — what they are

A guard is Laravel's auth context (api, web, sanctum). The guards config entry lists which guards receive ApiTables routes:

'guards' => ['api', 'web'],

Route prefixes per guard

Guard in configRoute prefixTypical use
api/api/api-table/control-tables/...SPA, mobile, token auth
web/api-table/control-tables/...Session-based Inertia apps
spa/spa/api-table/control-tables/...Custom guard name

Verify in your app

Run php artisan route:list --name=ApiTables — prefix depends on your RouteServiceProvider and guard config.

Route names

ApiTables.api.loadTable
ApiTables.web.queryTableData
ApiTables.api.rowTableAction

Useful for generating URLs in tests: route('ApiTables.api.loadTable', ['tableName' => 'users']).

Default middleware

'default_middlewares' => ['auth:sanctum'],

Applied to every table before your controller runs. Change only if your app uses a different API auth strategy:

'default_middlewares' => ['auth:api'],

Per-table middleware

Restrict sensitive tables to admins:

'tables' => [
    'payroll' => [
        'model' => App\Models\Payroll::class,
        'tableClass' => App\ApiTables\PayrollTable::class,
        'middlewares' => ['admin'],
    ],
],

Supported forms

FormExampleWhen to use
Alias'admin'Registered in bootstrap/app.php or Kernel
ClassEnsureAdmin::classStandard middleware class
Callable[PolicyMiddleware::class, 'handle']Custom logic with early abort

TablesMiddleware merges: default_middlewares + table middlewares and runs them through Laravel's pipeline.

How TablesMiddleware works (senior)

  1. Reads {tableName} from route
  2. Loads config("api-tables-config.tables.{tableName}.middlewares")
  3. Merges with default_middlewares
  4. Resolves aliases, classes, and callables
  5. Aborts 404 if tableName missing

Common auth debugging

SymptomCheck
401 on all tablesToken expired; wrong guard; Sanctum stateful domain
403 on one table onlyPer-table middleware
Works in web, fails in APIDifferent guards need separate tokens/sessions

Example: role-based table

// Only users with 'view-reports' permission
'middlewares' => ['can:view-reports'],

Ensure the permission middleware is registered in your app.

On this page