Laravel Yajra 数据表服务器端存在分页问题

Posted

技术标签:

【中文标题】Laravel Yajra 数据表服务器端存在分页问题【英文标题】:Laravel Yajra Datatable Server Side with pagination problems 【发布时间】:2018-06-19 12:51:16 【问题描述】:

我是 Laravel 的新手,我正在尝试使用具有服务器端功能的 Yajra Datatable 插件。该插件适用于少量记录,但我有大量大约 100000 条记录。

为了加快控制器中的处理速度,我使用 take(10) 限制查询的结果,并使用另一个查询来计算总结果。到目前为止一切都很好。

问题是如何管理研究。除了主要研究领域外,我还使用了individual column searching,但我不知道如何返回正确的记录数来管理个人搜索过滤器的分页。

我认为个人搜索键在$columns = $request->get('columns');,但我不知道如何管理计数的查询。

感谢您的宝贵建议。

html 查看代码:

<table id="oTable">
   <thead>
      <tr>
         <th>Action</th>
         <th>Brand</th>
         <th>Code</th>
         <th>Description</th>
      </tr> 
      <tr>
         <th class="no_search"></th>
         <th></th>
         <th></th>
         <th></th>
      </tr>
   </thead>
</table>

jQuery 代码:

$('#oTable').DataTable(
    dom: 'lfrtip',
    "processing": true,
    "serverSide": true,
    "ajax": '!! url('getRecords') !!',
    "columns": [
      data: 'items.id', name: 'items_id',
      data: 'brands.description', name: 'brands_description',
      data: 'items.code', name: 'items_code',
      data: 'items.description', name: 'items_description'
    ],
    columnDefs: [
      targets: 'no_sort', orderable: false
    ],
    initComplete: function () 

      this.api().columns().every(function () 
        var column = this;
        var columnClass = column.header().className;
        if (columnClass.indexOf('no_search') != false) 
          var input = document.createElement("input");
          $(input).addClass('form-control');
          $(input).appendTo($(column.header()).empty())
          .on('change', function () 
            column.search($(this).val(), false, false, true).draw();
          );
        
      );
    
  );

控制器的方法:

public function getRecords(Request $request) 

      $search = $request->input('search.value');
      $columns = $request->get('columns');

      $count_total = \DB::table('items')
                        ->join('brands', 'item.brand', '=', 'brands.code')
                        ->count();

      $count_filter = \DB::table('items')
                        ->join('brands', 'items.brand', '=', 'brands.code')
                        ->where(   'brands.description' , 'LIKE' , '%'.$search.'%')
                        ->orWhere( 'items.description' , 'LIKE' , '%'.$search.'%')
                        ->orWhere( 'items.code' , 'LIKE' , '%'.$search.'%')
                        ->count();

      $items= \DB::table('items')
        ->join('brands', 'items.brand', '=', 'brands.code')
        ->select(
            'items.id as items_id',
            'items.code as items_code',
            'items.description as items_description',
            'brands.description as brands_description'
        ) -> take(10);

        return Datatables::of($items)          
          ->with([
            "recordsTotal" => $count_total,
            "recordsFiltered" => $count_filter,
          ])
          ->rawColumns(['items_id','brands_description'])
          ->make(true);
    

【问题讨论】:

也许晚了,但试试这个包packagist.org/packages/acfbentveld/laravel-datatables。它会为您完成您描述的所有事情。 【参考方案1】:
 public function getRecords(Request $request) 
        //Use this way of your code
        $search  = $request->input('search.value');
        $columns = $request->get('columns');
        $order   = isset($_GET[ 'order' ]) ? $_GET[ 'order' ] : [];

        $count_total = \DB::table('items')
                          ->join('brands', 'item.brand', '=', 'brands.code')
                          ->count();

        $count_filter = \DB::table('items')
                           ->join('brands', 'items.brand', '=', 'brands.code')
                           ->where('brands.description', 'LIKE', '%' . $search . '%')
                           ->orWhere('items.description', 'LIKE', '%' . $search . '%')
                           ->orWhere('items.code', 'LIKE', '%' . $search . '%')
                           ->count();

        $items = \DB::table('items')
                    ->join('brands', 'items.brand', '=', 'brands.code')
                    ->select(
                        'items.id as items_id',
                        'items.code as items_code',
                        'items.description as items_description',
                        'brands.description as brands_description'
                    );
        foreach ($order as $o) 
            if(isset($columns[ $o[ 'column' ] ])) 
                $items = $items->orderBy($columns[ $o[ 'column' ] ][ 'name' ], $o[ 'dir' ]);
            
        
        $items = $items->take(10);

        return Datatables::of($items)
                         ->with([
                             "recordsTotal"    => $count_total,
                             "recordsFiltered" => $count_filter,
                         ])
                         ->rawColumns(['items_id', 'brands_description'])
                         ->make(TRUE);
    

【讨论】:

【参考方案2】:

您只需要替换控制器内部的方法并设置内容如下所述。 它会解决你的问题

    管理带有或不带有搜索的查询

    通过启用分页提高性能

    public function getRecords(Request $request) 
    
        $search = $request->input('search.value');
        $columns = $request->get('columns');
    
        $pageSize = ($request->length) ? $request->length : 10;
    
        $itemQuery = \DB::table('items')
        ->join('brands', 'items.brand', '=', 'brands.code');
    
        // $itemQuery->orderBy('items_id', 'asc');
        $itemCounter = $itemQuery->get();
        $count_total = $itemCounter->count();
    
        $count_filter = 0;
        if($search != '')
            $itemQuery->where( 'brands.description' , 'LIKE' , '%'.$search.'%')
                    ->orWhere( 'items.description' , 'LIKE' , '%'.$search.'%')
                    ->orWhere( 'items.code' , 'LIKE' , '%'.$search.'%')
            $count_filter = $itemQuery->count();
        
    
        $itemQuery->select(
            'items.id as items_id',
            'items.code as items_code',
            'items.description as items_description',
            'brands.description as brands_description'
        );
    
        $start = ($request->start) ? $request->start : 0;
        $itemQuery->skip($start)->take($pageSize);
        $items = $itemQuery->get();
    
        if($count_filter == 0)
            $count_filter = $count_total;
        
    
        return Datatables::of($items)          
            ->with([
            "recordsTotal" => $count_total,
            "recordsFiltered" => $count_filter,
            ])
            ->rawColumns(['items_id','brands_description'])
            ->make(true);
    
    

【讨论】:

【参考方案3】:

将实现用作服务,请在此处查看文档https://datatables.yajrabox.com/services/basic

【讨论】:

以上是关于Laravel Yajra 数据表服务器端存在分页问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Laravel 的一页上拥有多个 Yajra 数据表?

方法 Yajra\DataTables\CollectionDataTable::where 不存在

编辑列日期格式后不显示过滤日期 - Laravel Yajra Datatable

Laravel 8 Yajra DataTable 在同一页面刷新

如何在 yajra 数据表 laravel 中添加操作列

yajra datatable fractal从包含的属性中删除数据密钥