PHPackages                             manusiakemos/laravel-tanstack - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. manusiakemos/laravel-tanstack

ActiveLibrary[Database &amp; ORM](/categories/database)

manusiakemos/laravel-tanstack
=============================

Modern server-side datatable for Laravel, designed for TanStack Table frontends. Drop-in query builder with searching, sorting, filtering, and pagination.

0.1.0(1mo ago)10MITPHPPHP ^8.2CI passing

Since May 27Pushed 1mo agoCompare

[ Source](https://github.com/manusiakemos/laravel-tanstack)[ Packagist](https://packagist.org/packages/manusiakemos/laravel-tanstack)[ Docs](https://github.com/manusiakemos/laravel-tanstack)[ RSS](/packages/manusiakemos-laravel-tanstack/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (1)Dependencies (9)Versions (2)Used By (0)

Laravel DataTables for TanStack
===============================

[](#laravel-datatables-for-tanstack)

[![Latest Version](https://camo.githubusercontent.com/a21b84c859235f93a105e1f414e5c74a86f1ba71d34e5a1a3ff55217605cd804/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6d616e757369616b656d6f732f6c61726176656c2d74616e737461636b2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/manusiakemos/laravel-tanstack)[![Tests](https://camo.githubusercontent.com/a8466605def03d5b43842f4210421f4f18c08d4adb3b518710e3fa4d0e2679bf/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6d616e757369616b656d6f732f6c61726176656c2d74616e737461636b2f74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/manusiakemos/laravel-tanstack/actions)[![License](https://camo.githubusercontent.com/8640d90f66d8ba1f4547c998378bd7f1f10ccc0b3e5ea071f54c8ccd970851d5/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6d616e757369616b656d6f732f6c61726176656c2d74616e737461636b2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/manusiakemos/laravel-tanstack)

Modern server-side datatable for Laravel, purpose-built for [TanStack Table](https://tanstack.com/table) frontends (React, Vue, Svelte, Solid). Inspired by `yajra/laravel-datatables` but with a clean REST API instead of the legacy datatables.net protocol.

Use this when you have an Inertia (or any SPA) frontend, want server-side processing, and want to stop writing pagination + search + sort + filter boilerplate for every table.

Why this package
----------------

[](#why-this-package)

- **Three-line endpoints.** Whitelist columns, return the response. That's it.
- **REST-style query string.** Clean, browser-DevTools-friendly, easy to cache.
- **Type-safe FE companion.** Pairs with `@manusiakemos/laravel-tanstack-react` (separate package).
- **Eloquent or Query Builder.** Both supported, no extra setup.
- **No jQuery, no datatables.net baggage.**

Installation
------------

[](#installation)

```
composer require manusiakemos/laravel-tanstack
```

Publish the config (optional):

```
php artisan vendor:publish --tag=laravel-tanstack-config
```

Quick start
-----------

[](#quick-start)

```
use Manusiakemos\LaravelTanstack\DataTable;
use App\Models\User;

class UserDataTableController
{
    public function __invoke(Request $request)
    {
        return DataTable::for(User::query())
            ->searchable(['name', 'email'])
            ->sortable(['name', 'email', 'created_at'])
            ->filterable(['status', 'role']);
    }
}
```

Register it on a web route so it has access to the session (for Inertia auth):

```
Route::get('/datatable/users', UserDataTableController::class)->middleware('auth');
```

Done. The controller returns a `JsonResponse` automatically because `DataTable` implements `Responsable`.

API protocol
------------

[](#api-protocol)

### Request

[](#request)

```
GET /datatable/users?
  page=1&
  per_page=25&
  sort=name:asc,created_at:desc&
  search=hafiz&
  filter[status]=active&
  filter[role][]=admin&filter[role][]=editor

```

ParamDescription`page`1-indexed page number. Defaults to 1.`per_page`Rows per page. Clamped to `max_per_page` config.`sort`Comma-separated `column:direction` pairs.`search`Global search term across `searchable()` columns.`filter[col]=v`Equals filter.`filter[col][]=v1&filter[col][]=v2``whereIn` filter.### Response

[](#response)

```
{
  "data": [
    { "id": 1, "name": "Hafiz", "email": "hafiz@example.com" }
  ],
  "meta": {
    "page": 1,
    "per_page": 25,
    "total": 1234,
    "filtered": 89,
    "last_page": 4
  }
}
```

Features
--------

[](#features)

### Transform rows

[](#transform-rows)

```
DataTable::for(User::query()->with('role'))
    ->transform(fn ($user) => [
        'id' => $user->id,
        'name' => $user->name,
        'role' => $user->role->name,
        'status_label' => $user->status === 'active' ? 'Active' : 'Inactive',
    ]);
```

Or use an API Resource:

```
DataTable::for(User::query())->resource(UserResource::class);
```

### Custom search

[](#custom-search)

```
DataTable::for(User::query())
    ->search(fn ($q, $term) =>
        $q->whereRaw('LOWER(name) LIKE ?', ['%'.strtolower($term).'%'])
          ->orWhereHas('role', fn ($r) => $r->where('name', 'like', "%{$term}%"))
    );
```

### Custom sort column

[](#custom-sort-column)

For computed or relation columns:

```
DataTable::for(User::query())
    ->sortable(['name', 'role_name'])
    ->orderColumn('role_name', fn ($q, $dir) =>
        $q->orderBy(
            Role::select('name')->whereColumn('roles.id', 'users.role_id'),
            $dir
        )
    );
```

### Custom filter

[](#custom-filter)

```
DataTable::for(User::query())
    ->filterColumn('created_between', fn ($q, $value) =>
        $q->whereBetween('created_at', explode(',', $value))
    );
```

Request: `?filter[created_between]=2024-01-01,2024-12-31`

### Authorization

[](#authorization)

```
DataTable::for(User::query())
    ->authorize(fn () => Gate::allows('viewAny', User::class));
```

Returns 403 if the closure returns false.

### Default sort

[](#default-sort)

```
DataTable::for(User::query())
    ->sortable(['created_at'])
    ->defaultSort('created_at', 'desc');
```

### Skip total count

[](#skip-total-count)

For very large tables where `count(*)` over the unfiltered set is expensive:

```
DataTable::for(User::query())->skipTotal();
```

The response will have `meta.total = null`; frontend should rely on `filtered` only.

### Pagination limits

[](#pagination-limits)

```
DataTable::for(User::query())
    ->defaultPerPage(50)
    ->maxPerPage(200);
```

### Query builder macro

[](#query-builder-macro)

For one-liner usage:

```
return User::query()
    ->where('active', true)
    ->toDataTable()
    ->searchable(['name'])
    ->sortable(['name']);
```

Inertia + TanStack pattern
--------------------------

[](#inertia--tanstack-pattern)

The recommended setup: let Inertia render the page shell (layout, auth state, navigation), and let the table component fetch its own data from a separate JSON endpoint.

```
// Page rendered by Inertia
import { useDataTable } from '@manusiakemos/laravel-tanstack-react'

function UsersIndex() {
  const { table, loading } = useDataTable({
    endpoint: '/datatable/users',
    columns: [
      { accessorKey: 'name', header: 'Name' },
      { accessorKey: 'email', header: 'Email' },
    ],
  })

  return
}
```

The table state lives in React; the page shell stays Inertia-managed. No full-page reload on pagination.

Security notes
--------------

[](#security-notes)

- **Never call `->searchable()` or `->sortable()` with untrusted column names.** The package enforces whitelisting — only listed columns can be searched/sorted — but you must define the list yourself.
- **Use `->authorize()` for any non-public table.** Or check authorization in the controller before returning the DataTable.
- **The package is read-only** — it does not perform writes, so SQL injection surface is limited to filter values which are bound parameters.

Configuration
-------------

[](#configuration)

The full `config/laravel-tanstack.php`:

```
return [
    'default_per_page' => 25,
    'max_per_page' => 100,
    'case_insensitive' => true,
    'report_exceptions' => true,
];
```

Testing
-------

[](#testing)

```
composer test
```

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 11.x or 12.x

Roadmap
-------

[](#roadmap)

- PostgreSQL-specific `ILIKE` search optimization
- Laravel Scout integration for full-text search
- Vue 3 and Svelte FE companions
- Excel/CSV export endpoint
- Saved view / preset support

Contributing
------------

[](#contributing)

Contributions are welcome — bug reports, feature requests, and pull requests.

**Before opening a PR:**

1. Fork the repo and create a feature branch from `main`: ```
    git checkout -b feat/short-description
    ```
2. Install dependencies: ```
    composer install
    ```
3. Make your change. Keep the public API stable unless the PR is explicitly a breaking change.
4. Add or update tests under `tests/Feature` or `tests/Unit`. New features without tests will not be merged.
5. Run the full quality gate locally — it must pass before you push: ```
    composer format    # Laravel Pint
    composer analyse   # PHPStan
    composer test      # Pest
    ```
6. Update `CHANGELOG.md` under the `[Unreleased]` section. Use the Keep a Changelog categories: `Added`, `Changed`, `Deprecated`, `Removed`, `Fixed`, `Security`.
7. Open the PR against `main` with a clear description of the change, the motivation, and any breaking-change notes.

**Branch naming:** `feat/...`, `fix/...`, `docs/...`, `refactor/...`, `test/...`.

**Commit style:** Conventional Commits preferred (`feat:`, `fix:`, `docs:`, `chore:`, `refactor:`, `test:`).

**Issues:** When filing a bug, include the Laravel version, PHP version, a minimal reproduction, and the actual vs expected behavior. For feature requests, describe the use case before the proposed API.

License
-------

[](#license)

MIT.

###  Health Score

34

—

LowBetter than 75% of packages

Maintenance88

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity36

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

59d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/5b3317bafee76c331bf47d22aa81fef7acad05b26d7e03495a9935093416b75d?d=identicon)[manusiakemos](/maintainers/manusiakemos)

---

Top Contributors

[![manusiakemos](https://avatars.githubusercontent.com/u/31971611?v=4)](https://github.com/manusiakemos "manusiakemos (6 commits)")

---

Tags

laraveleloquentdatatablesinertiaquery buildertableserver-sidetanstack

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/manusiakemos-laravel-tanstack/health.svg)

```
[![Health](https://phpackages.com/badges/manusiakemos-laravel-tanstack/health.svg)](https://phpackages.com/packages/manusiakemos-laravel-tanstack)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.3M347](/packages/psalm-plugin-laravel)[api-platform/laravel

API Platform support for Laravel

58174.6k17](/packages/api-platform-laravel)[pressbooks/pressbooks

Pressbooks is an open source book publishing tool built on a WordPress multisite platform. Pressbooks outputs books in multiple formats, including PDF, EPUB, web, and a variety of XML flavours, using a theming/templating system, driven by CSS.

45444.2k1](/packages/pressbooks-pressbooks)[simplestats-io/laravel-client

Server-side analytics for Laravel that follows the full funnel from visit to registration to payment, attributed to the channel that drove it. Revenue, MRR, churn and ad-spend profit (ROAS/CAC) per channel. GDPR compliant, ad-blocker proof.

5022.6k](/packages/simplestats-io-laravel-client)[fleetbase/core-api

Core Framework and Resources for Fleetbase API

1235.9k21](/packages/fleetbase-core-api)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

255.2k](/packages/aedart-athenaeum)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
