Laravel 5.4搭配Datatables插件加载缓慢问题求助
解决Laravel 5.4 + Datatables大数据量加载缓慢的问题
首先得跟你说清楚为啥现在加载慢:你之前是把7000条数据全部传到前端,让浏览器里的Datatables去做分页、排序、搜索——浏览器处理这么多数据肯定扛不住,所以要等好几分钟。而控制器里dd($data['noticias'])快,是因为数据库查询本身就快,只是数据传到前端后的处理拖慢了速度。
不用怕Ajax!其实Laravel有专门的Datatables封装包,能帮你把大部分Ajax逻辑都搞定,你只需要跟着步骤改就行,不用自己写复杂的异步请求代码。
第一步:安装并配置Laravel Datatables包
Laravel 5.4对应的是yajra/laravel-datatables的8.x版本,先安装:
composer require yajra/laravel-datatables:8.*
然后在config/app.php里添加服务提供者和别名:
// 服务提供者(加到providers数组里) Yajra\Datatables\DatatablesServiceProvider::class, // 别名(加到aliases数组里) 'Datatables' => Yajra\Datatables\Facades\Datatables::class,
最后发布配置文件:
php artisan vendor:publish --provider="Yajra\Datatables\DatatablesServiceProvider"
第二步:修改控制器代码
把原来返回全量数据的逻辑拆成两个方法:一个返回视图,一个专门给Datatables提供Ajax数据。
假设你的控制器是NoticiaController,修改后大概是这样:
<?php namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; use App\Noticia; use Datatables; class NoticiaController extends Controller { // 只返回视图,不用传数据 public function index() { return view('admin.noticias.index'); } // 处理Datatables的Ajax请求 public function datatables() { // 只查询需要的字段,别用select('*'),减少数据传输 $noticias = Noticia::select(['id', 'titulo', 'contenido', 'created_at', 'updated_at']); return Datatables::of($noticias) // 如果需要添加操作按钮(编辑、删除),在这里定义 ->addColumn('acciones', function ($noticia) { return '<a href="'.route('noticias.edit', $noticia->id).'" class="btn btn-sm btn-primary">Editar</a> <form action="'.route('noticias.destroy', $noticia->id).'" method="POST" style="display:inline;"> '.csrf_field().' '.method_field('DELETE').' <button type="submit" class="btn btn-sm btn-danger" onclick="return confirm(\'¿Estás seguro?\')">Eliminar</button> </form>'; }) // 告诉Datatables这个字段是HTML,不用转义 ->rawColumns(['acciones']) ->make(true); } }
第三步:添加Ajax路由
在routes/web.php里新增一条处理Datatables请求的路由:
// 原来的视图路由 Route::get('admin/noticias', 'Admin\NoticiaController@index')->name('noticias.index'); // 新增的Ajax数据路由 Route::get('admin/noticias/datatables', 'Admin\NoticiaController@datatables')->name('noticias.datatables');
第四步:修改视图代码
把原来手动循环渲染表格的逻辑删掉,改成Datatables的Ajax初始化方式:
<!-- 只保留表格头部,tbody由Datatables自动填充 --> <table id="noticias-table" class="table table-striped"> <thead> <tr> <th>ID</th> <th>Título</th> <th>Contenido</th> <th>Creado en</th> <th>Actualizado en</th> <th>Acciones</th> </tr> </thead> </table> <script> $(document).ready(function() { $('#noticias-table').DataTable({ processing: true, // 显示加载状态提示 serverSide: true, // 开启服务器端处理(核心!所有分页/排序/搜索都在数据库层面完成) ajax: "{{ route('noticias.datatables') }}", // 指向我们刚才创建的Ajax路由 columns: [ { data: 'id', name: 'id' }, { data: 'titulo', name: 'titulo' }, { data: 'contenido', name: 'contenido' }, { data: 'created_at', name: 'created_at' }, { data: 'updated_at', name: 'updated_at' }, // 操作列不需要排序和搜索,所以禁用这两个功能 { data: 'acciones', name: 'acciones', orderable: false, searchable: false } ], // 可选:添加西班牙语语言包(如果你的后台是西语环境) language: { url: "//cdn.datatables.net/plug-ins/1.10.25/i18n/Spanish.json" } }); }); </script>
为啥这样就能变快?
现在的逻辑是:每次只加载当前页的数据(比如10条/20条),排序、搜索这些操作都是在数据库里完成的,而不是让浏览器处理7000条数据。Laravel Datatables包会自动根据前端发送的参数(比如当前页码、排序字段、搜索关键词)生成对应的SQL查询,完全不需要你手动写复杂的分页/过滤逻辑。
额外优化建议
- 给经常用来排序、搜索的字段(比如
titulo、created_at)添加数据库索引,进一步提升查询速度。 - 如果需要关联其他模型(比如
Noticia关联Categoria),可以用with('categoria')预加载关联数据,避免N+1查询问题。
内容的提问来源于stack exchange,提问作者nature
相关产品推荐
相关产品推荐

