Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Tables Laravel Package

laravel-enso/tables

Laravel Enso Tables provides a fluent backend API for building dynamic, data-driven tables in Laravel, with server-side querying, filtering, sorting, pagination, and customizable columns for Enso’s Vue interfaces.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Check compatibility before anything. The last release is from May 2018, which puts it in the Laravel 5.5–5.8 / PHP 7.x / Vue 2 era. Read the package composer.json and confirm it will even install in your app. On Laravel 10/11 you will almost certainly need a fork or to vendor the backend pieces manually.
  2. Understand the ecosystem coupling. This is part of Laravel Enso, not a standalone datatable. It assumes Enso's core (laravel-enso/enso), its permission/menu structure, and its frontend asset pipeline. If you are not building an Enso admin panel, budget time for extracting the Vue component and wiring the controller trait yourself.
  3. Install and publish.
    composer require laravel-enso/tables
    php artisan vendor:publish --provider="LaravelEnso\Tables\AppServiceProvider"
    
    Inspect the published config and the package's src/app/Services/Table and src/app/Traits directories first — they define the base class and the controller contract.
  4. First use case: a users list.
    // app/Tables/UsersTable.php
    namespace App\Tables;
    
    use App\Models\User;
    use LaravelEnso\Tables\App\Services\Table\Table;
    
    class UsersTable extends Table
    {
        protected function query()
        {
            return User::select(['id', 'name', 'email', 'created_at']);
        }
    
        protected function templatePath(): string
        {
            return app_path('Tables/Templates/users.json');
        }
    }
    
    {
      "columns": [
        { "label": "ID", "name": "id", "sortable": true },
        { "label": "Name", "name": "name", "sortable": true, "searchable": true },
        { "label": "Email", "name": "email", "searchable": true },
        { "label": "Created", "name": "created_at", "sortable": true }
      ],
      "buttons": ["create", "export"],
      "actions": ["edit", "destroy"]
    }
    
    Expose it through the controller trait:
    use LaravelEnso\Tables\App\Traits\Table;
    
    class UserController extends Controller
    {
        use Table;
    
        protected function init()
        {
            return UsersTable::class;
        }
    }
    
    Route::get('users/table', [UserController::class, 'index'])->name('users.table');
    
    Then render the component in your Vue view (exact prop names vary by version — read the component's props in resources/js):
    <vue-table :id="usersTable" name="users" route="users.table" />
    

Implementation Patterns

  • query() returns a builder, never results. The package applies search, sort, filters, pagination, and counts itself. Returning get() or paginate() defeats the whole design and is the most common first mistake.
  • Treat the JSON template as the API contract. Column name values must match the selected columns or explicit aliases. Keep templates in app/Tables/Templates and review them in code review like any other interface change.
  • Scope authorization inside query(). Apply a policy-driven scope (->visibleTo(auth()->user()) or equivalent) on the base builder, and still protect the route with middleware. Hiding buttons is not authorization.
  • Custom filters map to query scopes. Implement filters() returning filter objects (date, interval, select, search) and mirror the same keys in the template's filters block so the UI and backend agree.
  • Actions and bulk actions. Define actions() to control which row buttons render and the permission/route each requires. Keep destructive or bulk operations behind Enso permissions or explicit Gate checks.
  • meta() and extra() for aggregates. Use meta() for footer totals and extra() for side payloads like dropdown options. They run on every request, so keep them cheap and cached where possible.
  • Compose instead of copy. Extract shared columns and filters into traits or a base table; for near-identical tables, extend and override query() / templatePath() rather than duplicating JSON.
  • Reuse the same query for export. Make sure the export button honours active filters and hidden columns; otherwise exports drift from what the user sees.
  • Test the endpoint, not just the class. Feature-test with the XHR-style params (start, length, search, sort, filters) and assert both data and meta. Snapshot the template JSON to catch accidental contract changes.
  • Keep business logic on the server. Use the Vue table as a controlled component: pass filters in as props, listen for row events, and let the backend decide what is visible and actionable.

Gotchas and Tips

  • 2018 release, modern apps beware. Vue 2 and Bulma are baked in. Dropping this into a Vue 3 / Tailwind / Bootstrap project means rebuilding the frontend component and keeping only the server-side contract.
  • Enso is assumed, not optional. The package leans on Enso's structure, permissions, menu, and asset build. In a plain Laravel app you will wire the trait, route, and component manually.
  • Silent blank columns. A JSON name that does not match a selected column or alias renders an empty cell with no error. Alias computed columns explicitly and mark them "sortable": false unless you also handle sorting.
  • Relationships need joins and eager loading. user.name-style columns require joins plus careful searchable/sortable handling. Watch for N+1 queries and duplicate rows from one-to-many joins.
  • Sorting and search on computed columns often need raw expressions or subqueries; test them, because the package will happily generate invalid SQL.
  • Clear caches after template edits. If templates or config are cached, run php artisan config:clear / cache:clear, and rebuild frontend assets whenever JSON or column renderers change.
  • Large tables and counts. The package computes a total row count, which can be expensive. Add indexes for the filters you expose and avoid select *; on very large tables consider a capped or estimated total.
  • Timezone-sensitive dates. Interval filters and created_at sorting can shift across timezones or DST boundaries. Standardise on the app timezone and test around midnight.
  • Debug by replaying the XHR payload. Grab the request params from the browser network tab and hit the endpoint directly. The response shape quickly tells you whether the problem is the query, the template, or the Vue component.
  • Extend, don't edit vendor. Override base table methods and publish config; custom column renderers usually require registering a frontend component and rebuilding assets.
  • Isolate for the future. If you adopt it, pin versions and keep table definitions behind your own service layer so replacing the datatable later is a controller change, not a rewrite.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib