singlequote/laravel-datatables
A Laravel package for building server-side DataTables with a fluent, query-driven API, column configuration, and Blade-friendly rendering for fast, searchable, sortable admin listings.
Start by pinning the release and re-reading the package surface, since v4.0.28 is mostly additive:
composer require <vendor>/<package>:4.0.28
php artisan vendor:publish --provider="<Vendor>\<Package>\<PackageServiceProvider>"
php artisan migrate
Where to look first:
config/<package>.php — model swapping, table names, and any feature flags.src/Order.php (or the configured order model) — v4.0.28 adds a new method here; inspect the diff or git log -p to find its name and signature before using it.get() — this is where the new unique() method lands.First use case: fetch orders, then de-duplicate results that would otherwise repeat because of joins or eager-loading:
use Vendor\Package\Models\Order;
$orders = Order::query()
->where('status', 'paid')
->with('items')
->get()
->unique('customer_id')
->values();
If your package version exposes a custom result object, the same call is available directly on the value returned by get():
$orders = Order::where('status', 'paid')->get()->unique('customer_id');
The new Order method should be exercised in a scratch test or Tinker session first:
php artisan tinker
>>> $order = Order::first();
>>> $order->newMethod(...); // confirm name/signature from the v4.0.28 diff
De-duplicate at the collection boundary, not mid-query. The new unique() on get() is a PHP-side operation. Use it when the duplicate rows are an artifact of joins or relationship loading, and keep the query itself focused on filtering:
$orders = Order::query()
->whereBetween('created_at', [$from, $to])
->whereHas('items', fn ($q) => $q->where('sku', $sku))
->get()
->unique('id')
->values();
Wrap the new Order method in an application action. Release notes only say “new method added to order”, so treat it as a domain operation and isolate it:
final class ApplyOrderChange
{
public function __invoke(Order $order, array $payload): Order
{
return DB::transaction(function () use ($order, $payload) {
$order->newMethod($payload);
event(new OrderChanged($order));
return $order->refresh();
});
}
}
Use unique() consistently in read paths. If an endpoint returns orders, apply unique() before the API resource so pagination and counts are not misleading:
return OrderResource::collection(
$orders->unique('customer_id')->values()
);
Layer it into repositories. Return collections, not builders, and centralise the de-duplication rule:
public function paidOrders(): Collection
{
return Order::where('status', 'paid')
->get()
->unique('customer_id')
->values();
}
Test the release explicitly. Add a feature test for the new Order method and a unit test that asserts unique() keeps the first occurrence and preserves/reindexes keys as expected:
it('deduplicates orders by customer', function () {
$orders = Order::factory()->count(3)->create([
'customer_id' => 1,
]);
expect(Order::all()->unique('customer_id'))->toHaveCount(1);
});
unique() on get() is not SQL DISTINCT. It runs in PHP after all rows are fetched. For large tables, prefer ->distinct() or ->groupBy() in the query, and reserve get()->unique() for small, already-filtered result sets.unique() keeps the original keys, so JSON responses can serialise as objects instead of arrays. Chain ->values() when returning lists.unique('customer_id') compares loosely by default; use unique(fn ($order) => (string) $order->customer_id) or uniqueStrict() if IDs differ in type.Order method persists or mutates. If it writes, call it inside a transaction and refresh the model. If it dispatches events, make sure listeners are registered and idempotent.php artisan config:clear and php artisan cache:clear; stale config is a common source of “the new method does not exist” confusion.unique(): inspect the raw collection before and after (dump($orders->count(), $orders->unique('id')->count())) and log the SQL with DB::listen() or ->toSql() to confirm duplicates originate in the query.Order class. This keeps your code compatible if the package swaps implementations in a future release.How can I help you explore Laravel packages today?