Laravel 12 DataTables with Relationships & Column Filtering: Complete Guide

Author

Kritim Yantra

Apr 07, 2025

Laravel 12 DataTables with Relationships & Column Filtering: Complete Guide

Introduction

When working with relational data in Laravel DataTables, you often need to:

  1. Display related model data (e.g., show user's department name)
  2. Implement column-specific filtering
  3. Maintain server-side processing performance

This guide covers everything from basic relationship handling to advanced filtering techniques.


1. Setting Up Relationships in DataTables

1.1 Database Structure Example

users
  id - integer
  name - string
  email - string
  department_id - integer

departments
  id - integer
  name - string

1.2 Basic Relationship Setup

// User.php
public function department()
{
    return $this->belongsTo(Department::class);
}

1.3 Controller with Eager Loading

public function getUsers()
{
    $model = User::with('department');
    
    return DataTables::eloquent($model)
        ->addColumn('department_name', function(User $user) {
            return $user->department->name;
        })
        ->toJson();
}

2. Column Filtering Techniques

2.1 Individual Column Filters (Dropdowns)

<!-- Add above your table -->
<div class="row mb-3">
    <div class="col-md-3">
        <select class="form-control filter-select" data-column="3">
            <option value="">All Departments</option>
            @foreach($departments as $department)
                <option value="{{ $department->name }}">{{ $department->name }}</option>
            @endforeach
        </select>
    </div>
</div>

2.2 JavaScript Filter Implementation

let table = $('#users-table').DataTable({
    // ... standard config
});

$('.filter-select').on('change', function() {
    let column = $(this).data('column');
    table.column(column).search(this.value).draw();
});

3. Advanced Relationship Filtering

3.1 Server-Side Relationship Filtering

return DataTables::eloquent($model)
    ->filter(function ($query) {
        if (request()->has('department_filter')) {
            $query->whereHas('department', function($q) {
                $q->where('name', request('department_filter'));
            });
        }
    });

3.2 Dynamic Filter Form

// In controller index method
$departments = Department::pluck('name', 'id');
return view('users.index', compact('departments'));
<form id="filter-form">
    <select name="department_id" class="form-control">
        <option value="">All Departments</option>
        @foreach($departments as $id => $name)
            <option value="{{ $id }}">{{ $name }}</option>
        @endforeach
    </select>
    <button type="submit" class="btn btn-primary">Filter</button>
</form>
$('#filter-form').on('submit', function(e) {
    e.preventDefault();
    table.ajax.url("{{ route('users.data') }}?" + $(this).serialize()).load();
});

4. Handling Complex Relationships

4.1 Many-to-Many Relationships

// Filter users by their roles
->filter(function ($query) {
    if (request()->has('role')) {
        $query->whereHas('roles', function($q) {
            $q->where('name', request('role'));
        });
    }
})

4.2 Polymorphic Relationships

// Filter comments by commentable type
->filter(function ($query) {
    if (request()->has('commentable_type')) {
        $query->where('commentable_type', request('commentable_type'));
    }
})

5. Performance Optimization

5.1 Select Only Required Columns

return DataTables::eloquent($model)
    ->select(['users.id', 'users.name', 'departments.name as department_name'])
    ->join('departments', 'users.department_id', '=', 'departments.id')

5.2 Disable Searching on Unfilterable Columns

columns: [
    { data: 'id', searchable: false },
    { data: 'name' },
    { data: 'department_name', searchable: true }
]

5.3 Cache Frequent Queries

$departments = Cache::remember('departments.filter', 3600, function() {
    return Department::all();
});

6. Complete Example: User Management System

6.1 Final Controller

public function getUsers()
{
    $model = User::with('department', 'roles')
        ->select(['users.*']);
    
    return DataTables::eloquent($model)
        ->addColumn('department_name', function(User $user) {
            return $user->department->name;
        })
        ->addColumn('roles', function(User $user) {
            return $user->roles->pluck('name')->implode(', ');
        })
        ->filter(function ($query) {
            // Department filter
            if (request()->has('department_id')) {
                $query->where('department_id', request('department_id'));
            }
            
            // Role filter
            if (request()->has('role')) {
                $query->whereHas('roles', function($q) {
                    $q->where('name', request('role'));
                });
            }
            
            // Date range filter
            if (request()->has('date_from')) {
                $query->whereDate('created_at', '>=', request('date_from'));
            }
        })
        ->toJson();
}

6.2 Blade View

<table id="users-table" class="table">
    <thead>
        <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Email</th>
            <th>Department</th>
            <th>Roles</th>
            <th>Joined At</th>
        </tr>
    </thead>
</table>

<script>
$(document).ready(function() {
    $('#users-table').DataTable({
        processing: true,
        serverSide: true,
        ajax: {
            url: "{{ route('users.data') }}",
            data: function(d) {
                d.department_id = $('#department-filter').val();
                d.role = $('#role-filter').val();
            }
        },
        columns: [
            { data: 'id' },
            { data: 'name' },
            { data: 'email' },
            { data: 'department_name' },
            { data: 'roles' },
            { 
                data: 'created_at',
                render: function(data) {
                    return new Date(data).toLocaleDateString();
                }
            }
        ]
    });
    
    // Refresh table when filters change
    $('.filter').on('change', function() {
        $('#users-table').DataTable().ajax.reload();
    });
});
</script>

Conclusion

You've now learned how to:
✅ Display relational data in DataTables
✅ Implement column-specific filtering
✅ Handle complex relationship queries
✅ Optimize server-side performance

📌 Need help? Drop your questions below! 👇

Tags

Comments

No comments yet. Be the first to comment!

Please log in to post a comment:

Sign in with Google

Related Posts