amjadiqbal/laravel-gridjs
A Laravel wrapper for Grid.js that lets you build fast, interactive data tables with minimal effort. Render grids from Eloquent models or arrays, add sorting, searching, and pagination, and customize columns cleanly within your Blade views.
The package renders server-driven data grids and serves their rows from a separate data endpoint, authorised by a signed grid token embedded in the rendered markup. v1.0.2 changes the default security posture, so the very first thing to check is where your grids are rendered.
php artisan vendor:publish --tag=...), then run your migrations if the package ships any.bind_tokens, and the new allow_unbound_tokens (default false). These two keys determine almost every behaviour you will hit day to day.web middleware and an authenticated route:{{-- routes/web.php: Route::middleware('auth')->get('/orders', ...) --}}
<x-grid :source="$ordersGrid" />
Your first useful use case is the standard authenticated admin listing: a grid bound to the signed-in user, served from a route group with web + auth. Get that working before touching any config flags, because it is the path the package now optimises for and enforces.
Bind tokens to the user (default). With bind_tokens left on and allow_unbound_tokens off, tokens are signed against the current user. Rendering inside an authenticated web route is the supported path, and the data endpoint rejects tokens that aren't bound to the requesting user. This is the pattern to reach for on any dashboard, admin panel or tenant-scoped listing.
Public / read-only grids. If a grid must be visible to anonymous visitors (marketing pages, public directories), decide deliberately between the two options:
allow_unbound_tokens => true — keep binding logic in place but let the data endpoint accept tokens with no user attached. Rendering a grid with no signed-in user stops throwing and issues an unbound token.bind_tokens => false — turn binding off entirely for the whole application.Prefer the narrower of the two. allow_unbound_tokens is a per-deployment escape hatch that leaves bound grids bound; bind_tokens = false removes the protection globally, so reserve it for packages or apps where every grid is public.
Keep rendering inside web. Because tokens are derived from the session, render grids from controllers/views reached through the web middleware group. If you have an api route that returns HTML fragments containing grids, either add session middleware to that route or front it with a web route that renders the markup and lets the API only serve data.
Tests. Feature tests that render a grid page are the most likely place to trip the new exception. Use $this->actingAs($user) before rendering, and assert the data endpoint returns 200 for that user and 403 for a different one. Add a test that hits the data endpoint with a token from another session to lock in the binding behaviour.
Livewire / Inertia / partial reloads. Whatever renders the grid must run in the same session context as the subsequent fetch. Re-rendering a grid via a Livewire action is fine (session present); generating grid markup from a queued job or an artisan command is not — that HTML will now throw rather than quietly producing a token anyone could replay.
RuntimeException on render is the new normal. If you render a grid with no signed-in user and no session, v1.0.2 throws instead of issuing a token. The message names the fix. Almost always the answer is "move this view behind web + auth", not "flip the config flag". Treat the exception as a routing bug first and a config problem second.
403 on the data endpoint, not on the page. Unbound tokens are rejected at fetch time, so the grid renders (or used to) and then the table silently fails to load. When a grid looks empty, check the network tab for a 403 on the data request before debugging your query.
bind_tokens vs allow_unbound_tokens are not the same switch. bind_tokens = false disables binding entirely; allow_unbound_tokens = true merely permits tokens that ended up unbound. Enabling the second does not weaken bound grids. Enabling the first does. Document the choice in your config file so the next developer doesn't "fix" an exception by disabling binding globally.
Config caching. Both keys are config values. After changing them, run php artisan config:clear (or re-cache) — a stale cached config is the usual reason a fix "doesn't work" locally.
Don't cache or persist rendered grid HTML. Tokens are short-lived and user-bound; storing rendered markup in a response cache, a Blade fragment cache or a queue payload will hand one user's token to another, or serve an expired token that 403s. Cache the underlying query results instead and re-render the grid.
Token expiry. Tokens are designed to expire. Long-lived pages (a tab left open overnight) will start failing data fetches; plan for a client-side reload-on-403 rather than assuming the endpoint is broken.
Extension points to reach for before patching. If you need custom authorisation beyond "this token belongs to this user" — team scoping, record-level checks — do it at the controller or query layer behind the grid source rather than forking token generation. Keep the package's signing logic intact so future security patches land cleanly; 1.0.2 is a good reminder that this layer changes.
Upgrade note. This is a patch release with security consequences: if you were relying on 1.0.1's permissive behaviour (grids rendered outside web, or unbound tokens accepted at the endpoint), the upgrade is effectively breaking. Grep for grid renders in console commands, queued jobs, cached fragments and any non-web route before deploying, and set allow_unbound_tokens only where you have consciously decided the data is public.
How can I help you explore Laravel packages today?