santigarcor/laravel-vuetable
Laravel backend integration for the vue-table Vue.js component. Adds server-side pagination, sorting, searching, and filtering so Vue data tables work smoothly with Eloquent queries using minimal boilerplate.
composer require santigarcor/laravel-vuetable. The package auto-registers its service provider (Laravel 5.5+ package discovery); if you disable discovery, register it manually.php artisan vendor:publish --tag=config (or run vendor:publish and pick the package's provider). The config typically controls the default per_page / items-per-page value and default sort column.src/) before the README. At 27 stars and a 2021 release, the code is small and the README may be stale — the controller base class, the model trait, and the config are the whole surface area.vuetable front end. Create a controller that extends the package's base controller, point it at a model (or a query builder), register an API route, and have vuetable hit it. The front end sends page, per_page, sort, order, q, and filter query parameters; the package translates them into Eloquent and returns { data, total, ... }.// app/Http/Controllers/Api/UsersTableController.php
class UsersTableController extends VueTableController
{
protected $model = User::class;
}
// routes/api.php
Route::get('users/table', [UsersTableController::class, 'index']);
<vuetable api-url="/api/users/table" :fields="['name', 'email', 'created_at']" />
index endpoint. Keep your normal REST UserController separate; mixing a generic index with table semantics gets confusing fast when you need to return different column sets.getQuery() / query()). Add with(), select(), scopes, and tenant constraints there instead of duplicating the package logic:protected function getQuery()
{
return parent::getQuery()
->with(['company:id,name'])
->where('is_active', true);
}
sort directly to orderBy. Maintain a $sortable = ['name', 'email', 'created_at'] array and reject anything outside it. Same for filterable fields.q) should map to a defined set of columns (name, email), not where like across every column — that breaks on numeric/text mixed columns and is slow on large tables.filter=email|jane@… in vuetable conventions. Normalize and validate the field name, then apply where (or where like for text). Treat the operator as fixed per-field; don't parse user-supplied operators.UserTableResource::collection(...) and preserve the data/total envelope the front end expects.fields entry, missing relationships produce N+1 queries on paginated tables — the most common production failure with this pattern.data, total, per_page) and assert sorting/filtering behavior, not just status 200. This is cheap and catches the whitelist regressions that matter.composer.json.count(*) performance. The package needs a total for pagination. For large tables, combine with simplePaginate or move to a keyset approach — the built-in count query is often the slowest part of the request.vuetable is picky about the envelope keys (data, total). If you wrap in Resource::collection without setting $wrap or the controller's response mapping, the front end renders an empty table with no error. Test the raw JSON.join in the query override; orderBy('company.name') silently fails or errors.filter=email| arrives as an empty string. Guard against applying where('email', '') — it looks like a bug to users ("why did my table go blank?").per_page naming. Vueteable uses per_page; Laravel uses perPage. The package translates it, but if you add a custom paginator or simplePaginate, keep the config's default and cap it (e.g. min($request->per_page, 100)) to prevent per_page=999999.vendor/. If you must patch, fork under your own namespace and keep the composer constraint pinned.sort, order, filter, q, per_page) at the top of the query override. When a table misbehaves, the front end is almost always sending a param shape you didn't expect.How can I help you explore Laravel packages today?