如何在Laravel 9的DataTable AJAX分页中添加自定义过滤器

223 阅读3分钟

DataTable默认有一个单一的搜索框,用于全局搜索。

如果默认的搜索过滤器不能满足你的要求,那么你可以定制和添加你自己的过滤器元素,如 - 下拉菜单,日期过滤器,文本框等。

在本教程中,我展示了如何在Laravel 9的DataTable AJAX分页中添加自定义过滤器。

How to add Custom filter in DataTable AJAX pagination in Laravel 9

演示

1. 数据库配置

打开.env 文件。

指定主机、数据库名称、用户名和密码。

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=tutorial
DB_USERNAME=root
DB_PASSWORD=

2. 表的结构

  • 使用迁移创建一个新的表employees
php artisan make:migration create_employees_table
  • 现在,从项目根目录导航到database/migrations/ 文件夹。
  • 找到一个以create_employees_table 结尾的PHP文件并打开它。
  • up() 方法中定义表的结构。
public function up()
{
    Schema::create('employees', function (Blueprint $table) {
       $table->bigIncrements('id');
       $table->string('username',60);
       $table->string('name');
       $table->string('email',80);
       $table->string('city',80);
       $table->string('gender',10);
       $table->timestamps();
    });
}
  • 运行迁移------。
php artisan migrate
  • 表已经创建,我向它添加了一些记录。

3. 下载

  • 这里下载DataTables库,同时下载jQuery库。
  • 将下载的文件解压到public/ 文件夹中。
  • 同时,将jQuery库复制到public/ 文件夹中。
  • 你也可以使用CDN。
<!-- Datatable CSS -->
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.25/css/jquery.dataTables.min.css"/>

<!-- jQuery Library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

<!-- Datatable JS -->
<script src="https://cdn.datatables.net/1.10.25/js/jquery.dataTables.min.js"></script>

4. 模型

  • 创建Employees 模型。
php artisan make:model Employees
  • 打开app/Models/Employees.php 文件。
  • 使用$fillable 属性指定大量可分配的模型属性 - 用户名、姓名、电子邮件、性别和城市。

完成的代码

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Employees extends Model
{
   use HasFactory;

   protected $fillable = [
      'username','name','email','gender','city'
   ];
}

5. 控制器

  • 创建EmployeesController 控制器。
php artisan make:controller EmployeesController
  • 导入Employees 模型。

创建2个方法 -

  • **index() -**从employees 表中获取不同的城市记录并分配给$data['cities'] 。加载index 视图并传递给$data
  • **getEmployees() -**使用这个方法返回DataTable记录。

读取DataTable的值并将其分配给变量。

读取自定义过滤器的值(searchCity,searchGender和searchName)并将其分配给变量。

employees 表中获取带和不带过滤器的总记录。在计算记录时,如果变量值不是空的,在where 子句中添加自定义过滤器。

employees 表中获取记录,如果变量不为空,在where 子句中指定自定义过滤器的值。

在获取的记录上循环,并将值分配给$data_arr 数组。

用draw, iTotalRecords, iTotalDisplayRecords, 和aaData键初始化$response 数组。

以JSON格式返回$response 数组。

完成的代码

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Employees;

class EmployeesController extends Controller {

   public function index(){

      $data['cities'] = Employees::distinct()->get(['city']);

      return view('index',$data);
   }

   // Fetch DataTable data
   public function getEmployees(Request $request){

      ## Read value
      $draw = $request->get('draw');
      $start = $request->get("start");
      $rowperpage = $request->get("length"); // Rows display per page

      $columnIndex_arr = $request->get('order');
      $columnName_arr = $request->get('columns');
      $order_arr = $request->get('order');
      $search_arr = $request->get('search');

      $columnIndex = $columnIndex_arr[0]['column']; // Column index
      $columnName = $columnName_arr[$columnIndex]['data']; // Column name
      $columnSortOrder = $order_arr[0]['dir']; // asc or desc
      $searchValue = $search_arr['value']; // Search value

      // Custom search filter 
      $searchCity = $request->get('searchCity');
      $searchGender = $request->get('searchGender');
      $searchName = $request->get('searchName');

      // Total records
      $records = Employees::select('count(*) as allcount');

      ## Add custom filter conditions
      if(!empty($searchCity)){
          $records->where('city',$searchCity);
      }
      if(!empty($searchGender)){
          $records->where('gender',$searchGender);
      }
      if(!empty($searchName)){
          $records->where('name','like','%'.$searchName.'%');
      }
      $totalRecords = $records->count();

      // Total records with filter
      $records = Employees::select('count(*) as allcount')->where('name', 'like', '%' .$searchValue . '%');

      ## Add custom filter conditions
      if(!empty($searchCity)){
         $records->where('city',$searchCity);
      }
      if(!empty($searchGender)){
         $records->where('gender',$searchGender);
      }
      if(!empty($searchName)){
         $records->where('name','like','%'.$searchName.'%');
      }
      $totalRecordswithFilter = $records->count();

      // Fetch records
      $records = Employees::orderBy($columnName,$columnSortOrder)
                 ->select('users_4.*')
                 ->where('users_4.name', 'like', '%' .$searchValue . '%');
      ## Add custom filter conditions
      if(!empty($searchCity)){
         $records->where('city',$searchCity);
      }
      if(!empty($searchGender)){
         $records->where('gender',$searchGender);
      }
      if(!empty($searchName)){
         $records->where('name','like','%'.$searchName.'%');
      }
      $employees = $records->skip($start)
                   ->take($rowperpage)
                   ->get();

      $data_arr = array();
      foreach($employees as $employee){

         $username = $employee->username;
         $name = $employee->name;
         $email = $employee->email;
         $gender = $employee->gender;
         $city = $employee->city;

         $data_arr[] = array(
             "username" => $username,
             "name" => $name,
             "email" => $email,
             "gender" => $gender,
             "city" => $city,
         );
      }

      $response = array(
         "draw" => intval($draw),
         "iTotalRecords" => $totalRecords,
         "iTotalDisplayRecords" => $totalRecordswithFilter,
         "aaData" => $data_arr
      );

      return response()->json($response); 
   }

}

6. 路线

  • 打开routes/web.php 文件。
  • 定义2个路由 -
    • **/ -**加载index 视图。
    • **/getEmployees -**这是AJAX请求的GET类型的路线,以加载可数据化的数据。
<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\EmployeesController;

Route::get('/', [EmployeesController::class, 'index']); 
Route::get('/getEmployees', [EmployeesController::class, 'getEmployees'])->name('getEmployees');

7. 视图

resources/views/ 中创建index.blade.php 文件。

包括DataTables和jQuery库在<head > 部分。

HTML -

  • 自定义过滤器

我创建了3个过滤元素 -

    • 第一个元素是一个下拉元素,用于存储城市列表。
    • 第2个元素是一个下拉元素,存储性别名称。
    • 第3个元素是一个文本框元素,用于按姓名过滤记录。
  • 数据表

创建<table id="empTable" > 来初始化数据表格。


脚本 -

#empTable 上初始化DataTable,并将实例分配给empTable 。向route('getEmployees') 发送AJAX请求。

传递自定义过滤值

使用data 选项来发送自定义过滤值 -data.searchCity,data.searchGender, 和data.searchName

columns 选项中指定在成功回调时被读取的键名。

在#sel_city,#sel_gender上定义change 事件,在#searchName上定义keyup 事件。

当事件触发时,在DataTable实例上调用draw() -empTable.draw(); 。使用这个重绘DataTable。

完成的代码

<!DOCTYPE html>
<html>
<head>
   <title>How to add Custom filter in DataTable AJAX pagination in Laravel 9</title>

   <!-- Meta -->
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   <meta charset="utf-8">

   <!-- Datatable CSS -->
   <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.25/css/jquery.dataTables.min.css"/>

   <!-- jQuery Library -->
   <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

   <!-- Datatable JS -->
   <script src="https://cdn.datatables.net/1.10.25/js/jquery.dataTables.min.js"></script>

</head>
<body>

   <!-- Search filter -->
   <div>
       <!-- City -->
       <select id='sel_city'>
          <option value=''>-- Select city --</option>

          @foreach($cities as $city){
             <option value='{{ $city->city }}'>{{ $city->city }}</option>
          @endforeach
       </select>

       <!-- Gender -->
       <select id='sel_gender'>
          <option value=''>-- Select Gender --</option>
          <option value='male'>Male</option>
          <option value='female'>Female</option>
       </select>

       <!-- Name -->
       <input type="text" id="searchName" placeholder="Search Name">
   </div>

   <table id='empTable' width='100%' border="1" style='border-collapse: collapse;'>
      <thead>
         <tr>
            <th>Username</th>
            <th>Name</th>
            <th>Email</th>
            <th>Gender</th>
            <th>City</th>
         </tr>
      </thead>
   </table>

   <!-- Script -->
   <script type="text/javascript"> 
   $(document).ready(function(){

      // DataTable
      var empTable = $('#empTable').DataTable({
          processing: true,
          serverSide: true,
          ajax: {
             url:"{{route('getEmployees')}}",
             data: function(data){
                data.searchCity = $('#sel_city').val();
                data.searchGender = $('#sel_gender').val();
                data.searchName = $('#searchName').val();
             }
          },
          columns: [
             { data: 'username' },
             { data: 'name' },
             { data: 'email' },
             { data: 'gender' },
             { data: 'city' },
          ]
      });

      $('#sel_city,#sel_gender').change(function(){
         empTable.draw();
      });

      $('#searchName').keyup(function(){
         empTable.draw();
      });

   });
   </script>
</body>
</html>

8. 演示

查看演示


9. 总结

当自定义过滤器事件被触发时,你需要在DataTable实例上调用draw()来获取过滤的记录。

如果你的项目是在Laravel 8上,你可以使用同样的代码。

如果你觉得这个教程有帮助,那么别忘了分享。