PHPackages                             jimmyahalpara/laravel-datatable - 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. jimmyahalpara/laravel-datatable

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

jimmyahalpara/laravel-datatable
===============================

A powerful Laravel package for building advanced DataTable filters with column filtering, global search, and custom filters

1.0.1(6mo ago)01MITPHPPHP ^8.1

Since Oct 16Pushed 6mo agoCompare

[ Source](https://github.com/jimmyahalpara/laravel-datatable)[ Packagist](https://packagist.org/packages/jimmyahalpara/laravel-datatable)[ RSS](/packages/jimmyahalpara-laravel-datatable/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (2)Dependencies (8)Versions (3)Used By (0)

Laravel DataTable Package
=========================

[](#laravel-datatable-package)

[![Latest Version on Packagist](https://camo.githubusercontent.com/e5997233bcd987bf9ee19796d76841f5d84b295ca3260b8aa50174fea7b6fcd9/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6a696d6d796168616c706172612f6c61726176656c2d646174617461626c652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/jimmyahalpara/laravel-datatable)[![Total Downloads](https://camo.githubusercontent.com/91ef862fe5642172834acfbe63d2cc55a66ec2f5349a06e658f2b1f6c37217ab/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6a696d6d796168616c706172612f6c61726176656c2d646174617461626c652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/jimmyahalpara/laravel-datatable)[![License](https://camo.githubusercontent.com/f72e145e3046c349492b19c5c1039f556cc0b889b107fe9aeaec82510ff9aae3/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6a696d6d796168616c706172612f6c61726176656c2d646174617461626c652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/jimmyahalpara/laravel-datatable)[![PHP Version](https://camo.githubusercontent.com/8e8fbad08708aa7e6213e1afe1b184fdf13c9ac816836155e380e5c40aaea371/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f6a696d6d796168616c706172612f6c61726176656c2d646174617461626c652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/jimmyahalpara/laravel-datatable)

A powerful Laravel package for building advanced DataTable functionality with column filtering, global search, custom filters, sorting, and pagination. This package provides a fluent, type-safe API for creating complex data tables with minimal code.

Features
--------

[](#features)

- 🔍 **Global Search**: Search across multiple columns with configurable search types
- 🎯 **Column Filtering**: Apply specific filters to individual columns
- 🔧 **Custom Filters**: Create complex custom filtering logic with callables
- 📊 **Sorting**: Multi-column sorting with validation
- 📄 **Pagination**: Built-in pagination with customizable page sizes
- 🏗️ **Fluent API**: Chainable methods for clean, readable code
- 🎨 **Resource Integration**: Seamless integration with Laravel API resources
- 📤 **Export Support**: Built-in download functionality with custom mappers
- 🔒 **Type Safe**: Full PHP 8.1+ type hints and strict typing
- 🧪 **Well Tested**: Comprehensive test suite with high code coverage
- ⚡ **Performance**: Optimized queries with relation-aware filtering

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

[](#requirements)

- PHP 8.1+
- Laravel 9.0+

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

[](#installation)

You can install the package via composer:

```
composer require jimmyahalpara/laravel-datatable
```

The package will automatically register itself via Laravel's package discovery.

Optionally, you can publish the configuration file:

```
php artisan vendor:publish --tag="datatable-config"
```

Quick Start
-----------

[](#quick-start)

Here's a simple example to get you started:

```
use JimmyAhalpara\LaravelDatatable\DataTableService;
use JimmyAhalpara\LaravelDatatable\Filters\ColumnFilter;
use JimmyAhalpara\LaravelDatatable\Filters\GlobalFilter;
use App\Models\User;

class UserController extends Controller
{
    public function index(Request $request)
    {
        $users = User::query();

        $dataTable = DataTableService::make($users)
            ->setGlobalFilters([
                GlobalFilter::make('name')->type('contains'),
                GlobalFilter::make('email')->type('contains'),
            ])
            ->setColumnFilters([
                ColumnFilter::make('status')->type('equal'),
                ColumnFilter::make('created_at')->cast(fn($date) => Carbon::parse($date)),
            ])
            ->fillFromRequest($request);

        return $dataTable->render();
    }
}
```

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

[](#configuration)

The package comes with a configuration file that allows you to customize default behavior:

```
return [
    // Default number of items per page
    'default_items_per_page' => 10,

    // Maximum items per page (prevents performance issues)
    'max_items_per_page' => 100,

    // Default search type for filters
    'default_search_type' => 'contains',

    // Enable case insensitive search by default
    'case_insensitive' => true,

    // Download configuration
    'download' => [
        'max_execution_time' => 1800, // 30 minutes
        'default_filename' => 'export',
        'default_format' => 'xlsx',
    ],

    // Cache configuration
    'cache' => [
        'enabled' => false,
        'ttl' => 300, // 5 minutes
        'prefix' => 'datatable',
    ],
];
```

Usage Guide
-----------

[](#usage-guide)

### Creating a DataTable Service

[](#creating-a-datatable-service)

Start by creating a DataTable service with an Eloquent builder:

```
use JimmyAhalpara\LaravelDatatable\DataTableService;
use App\Models\Post;

$posts = Post::with('user', 'categories');
$dataTable = DataTableService::make($posts);
```

### Global Filters

[](#global-filters)

Global filters are applied when the user performs a global search. They typically search across multiple columns:

```
use JimmyAhalpara\LaravelDatatable\Filters\GlobalFilter;

$dataTable->setGlobalFilters([
    GlobalFilter::make('title')
        ->type(GlobalFilter::TYPE_CONTAINS)
        ->caseInsensitive(true),

    GlobalFilter::make('content')
        ->type(GlobalFilter::TYPE_CONTAINS),

    // Search in related models
    GlobalFilter::make('user.name')
        ->type(GlobalFilter::TYPE_CONTAINS),
]);
```

#### Global Filter Options

[](#global-filter-options)

- **Search Types**: `contains`, `startsWith`, `endsWith`, `equal`
- **Case Sensitivity**: Enable/disable case-insensitive search
- **Logical Operators**: `AND`, `OR` (defaults to `OR` for global search)
- **Value Casting**: Transform search values before applying

```
GlobalFilter::make('published_at')
    ->type('equal')
    ->cast(function ($value) {
        return Carbon::parse($value)->format('Y-m-d');
    });
```

### Column Filters

[](#column-filters)

Column filters are applied to specific columns based on user input:

```
use JimmyAhalpara\LaravelDatatable\Filters\ColumnFilter;

$dataTable->setColumnFilters([
    // Simple equality filter
    ColumnFilter::make('status')
        ->type(ColumnFilter::TYPE_EQUAL),

    // Case-insensitive contains filter
    ColumnFilter::make('title')
        ->type(ColumnFilter::TYPE_CONTAINS)
        ->caseInsensitive(true),

    // Filter with value transformation
    ColumnFilter::make('price')
        ->type(ColumnFilter::TYPE_EQUAL)
        ->cast(fn($value) => (float) $value),

    // Relation filtering
    ColumnFilter::make('category.name')
        ->type(ColumnFilter::TYPE_EQUAL),
]);
```

#### Column Filter Features

[](#column-filter-features)

**Array Value Support**: Column filters automatically handle array values using `IN` clauses:

```
// Request: filter[status][] = ['active', 'pending']
// Generates: WHERE status IN ('active', 'pending')
```

**Relation Support**: Filter on related model columns:

```
// This will use whereHas() automatically
ColumnFilter::make('user.email')
    ->type(ColumnFilter::TYPE_CONTAINS)
```

### Custom Filters

[](#custom-filters)

For complex filtering logic, use custom filters with callables:

```
use JimmyAhalpara\LaravelDatatable\Filters\CustomFilter;

$dataTable->setCustomFilters([
    CustomFilter::make(function ($builder, $requestData) {
        // Age range filter
        if (isset($requestData['age_min'], $requestData['age_max'])) {
            $builder->whereBetween('age', [
                $requestData['age_min'],
                $requestData['age_max']
            ]);
        }

        // Complex date filtering
        if (isset($requestData['date_range'])) {
            [$start, $end] = explode(' to ', $requestData['date_range']);
            $builder->whereBetween('created_at', [
                Carbon::parse($start)->startOfDay(),
                Carbon::parse($end)->endOfDay(),
            ]);
        }

        // Conditional filtering
        if (isset($requestData['include_archived']) && !$requestData['include_archived']) {
            $builder->whereNull('archived_at');
        }
    }),
]);
```

### Sorting

[](#sorting)

Configure multi-column sorting with validation:

```
$dataTable->setSortBy([
    ['key' => 'created_at', 'order' => 'desc'],
    ['key' => 'name', 'order' => 'asc'],
]);
```

Sorting can also be handled automatically from request parameters:

```
// Frontend request
{
    "sortBy": [
        {"key": "name", "order": "asc"},
        {"key": "created_at", "order": "desc"}
    ]
}
```

### Pagination

[](#pagination)

Control pagination settings:

```
$dataTable
    ->setPage(1)
    ->setItemsPerPage(25);
```

The service automatically validates pagination parameters and applies limits based on configuration.

### Resource Integration

[](#resource-integration)

Integrate with Laravel API Resources for consistent JSON responses:

```
use App\Http\Resources\PostResource;

$dataTable
    ->setResourceClass(PostResource::class)
    ->fillFromRequest($request);

return $dataTable->render();
```

This returns a structured response:

```
{
    "current_page": 1,
    "data": [...],
    "first_page_url": "http://localhost/posts?page=1",
    "from": 1,
    "last_page": 5,
    "last_page_url": "http://localhost/posts?page=5",
    "next_page_url": "http://localhost/posts?page=2",
    "path": "http://localhost/posts",
    "per_page": 10,
    "prev_page_url": null,
    "to": 10,
    "total": 50
}
```

### Export/Download Functionality

[](#exportdownload-functionality)

Enable data export with custom formatting:

```
$dataTable
    ->setDownloadColumns(['name', 'email', 'created_at', 'status'])
    ->setDownloadMapper(function ($item) {
        return [
            'Name' => $item->name,
            'Email' => $item->email,
            'Registration Date' => $item->created_at->format('Y-m-d H:i:s'),
            'Status' => ucfirst($item->status),
        ];
    });

// Check if download is requested
if ($dataTable->expectsDownload()) {
    return $dataTable->render(); // Returns download response
}
```

### Request Integration

[](#request-integration)

Automatically populate the DataTable from HTTP requests:

```
// The request can contain:
// - page: Page number
// - itemsPerPage: Items per page
// - sortBy: Array of sorting configurations
// - filter: Object containing all filter values
// - download: Boolean flag for export

$dataTable->fillFromRequest($request);
return $dataTable->render();
```

Example request structure:

```
{
    "page": 2,
    "itemsPerPage": 25,
    "sortBy": [
        {"key": "name", "order": "asc"}
    ],
    "filter": {
        "search": "john doe",
        "status": "active",
        "category_id": [1, 2, 3],
        "date_range": "2023-01-01 to 2023-12-31"
    },
    "download": false
}
```

Advanced Usage
--------------

[](#advanced-usage)

### Method Chaining

[](#method-chaining)

The package supports full method chaining for clean, readable code:

```
return DataTableService::make(User::with('posts'))
    ->setGlobalFilters([
        GlobalFilter::make('name')->type('contains'),
        GlobalFilter::make('email')->type('contains'),
    ])
    ->setColumnFilters([
        ColumnFilter::make('status')->type('equal'),
        ColumnFilter::make('posts.title')->type('contains'),
    ])
    ->setCustomFilters([
        CustomFilter::make(function ($builder, $data) {
            if (isset($data['has_posts'])) {
                $builder->has('posts');
            }
        }),
    ])
    ->setSortBy([['key' => 'created_at', 'order' => 'desc']])
    ->setItemsPerPage(50)
    ->setResourceClass(UserResource::class)
    ->setDownloadColumns(['name', 'email', 'posts_count'])
    ->fillFromRequest($request)
    ->render();
```

### Complex Filtering Example

[](#complex-filtering-example)

```
class ProductController extends Controller
{
    public function index(Request $request)
    {
        $products = Product::with(['category', 'brand', 'reviews']);

        $dataTable = DataTableService::make($products)
            ->setGlobalFilters([
                GlobalFilter::make('name')->type('contains'),
                GlobalFilter::make('description')->type('contains'),
                GlobalFilter::make('sku')->type('startsWith'),
                GlobalFilter::make('category.name')->type('contains'),
                GlobalFilter::make('brand.name')->type('contains'),
            ])
            ->setColumnFilters([
                ColumnFilter::make('category_id')->type('equal'),
                ColumnFilter::make('brand_id')->type('equal'),
                ColumnFilter::make('status')
                    ->type('equal')
                    ->caseInsensitive(false),
                ColumnFilter::make('price')
                    ->type('equal')
                    ->cast(fn($value) => (float) $value),
                ColumnFilter::make('is_featured')
                    ->type('equal')
                    ->cast(fn($value) => (bool) $value),
            ])
            ->setCustomFilters([
                CustomFilter::make(function ($builder, $data) {
                    // Price range filter
                    if (isset($data['price_min'])) {
                        $builder->where('price', '>=', (float) $data['price_min']);
                    }
                    if (isset($data['price_max'])) {
                        $builder->where('price', '= ?', [(float) $data['min_rating']]);
                        });
                    }

                    // Availability filter
                    if (isset($data['in_stock']) && $data['in_stock']) {
                        $builder->where('stock_quantity', '>', 0);
                    }

                    // Date range filter
                    if (isset($data['created_from'])) {
                        $builder->whereDate('created_at', '>=', $data['created_from']);
                    }
                    if (isset($data['created_to'])) {
                        $builder->whereDate('created_at', '
