树状表格

树状表格支持分页和点击加载功能,特别适合用来展示数据量较大的多层级结构数据。

树状表格 - 图1

表结构和模型

要使用树状表格,要遵守约定的表结构:

{tip} 此表结构和模型可完全兼容 模型树

  1. CREATE TABLE `demo_categories` (
  2. `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  3. `parent_id` int(11) NOT NULL DEFAULT '0',
  4. `order` int(11) NOT NULL DEFAULT '0', // order 字段不是必须的,不设置也可以
  5. `title` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
  6. `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  7. `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  8. PRIMARY KEY (`id`)
  9. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

上面的表格结构里面有三个必要的字段parent_idtitle,其它字段没有要求。

对应的模型为app/Models/Category.php:

{tip} 为了便于阅读,这里不再展示 Repository 代码。

  1. <?php
  2. namespace App\Models\Demo;
  3. use Dcat\Admin\Traits\ModelTree;
  4. use Illuminate\Database\Eloquent\Model;
  5. class Category extends Model
  6. {
  7. use ModelTree;
  8. protected $table = 'demo_categories';
  9. }

表结构中的三个字段parent_idordertitle的字段名也是可以修改的:

  1. <?php
  2. namespace App\Models\Demo;
  3. use Dcat\Admin\Traits\ModelTree;
  4. use Illuminate\Database\Eloquent\Model;
  5. class Category extends Model
  6. {
  7. use ModelTree;
  8. protected $table = 'demo_categories';
  9. protected $titleColumn = 'name';
  10. protected $orderColumn = 'sort';
  11. protected $parentColumn = 'pid';
  12. }

如果你的数据表不需要 order 字段排序,则在模型中添加如下代码即可

  1. <?php
  2. namespace App\Models\Demo;
  3. use Dcat\Admin\Traits\ModelTree;
  4. use Illuminate\Database\Eloquent\Model;
  5. class Category extends Model
  6. {
  7. use ModelTree;
  8. protected $table = 'demo_categories';
  9. // 返回空值即可禁用 order 字段
  10. public function getOrderColumn()
  11. {
  12. return null;
  13. }
  14. }

使用

通过调用 Grid\Column::tree 方法即可开启树状表格功能,开启之后默认只查询最顶级节点的数据,子节点数据需要点击加载

  1. <?php
  2. namespace App\Admin\Controllers\Demo;
  3. use App\Models\Category;
  4. use Dcat\Admin\Grid;
  5. use Dcat\Admin\Controllers\AdminController;
  6. class CategoryController extends AdminController
  7. {
  8. protected function grid()
  9. {
  10. return Grid::make(new Category(), function (Grid $grid) {
  11. $grid->id('ID')->bold()->sortable();
  12. $grid->title->tree(); // 开启树状表格功能
  13. $grid->order;
  14. $grid->created_at;
  15. $grid->updated_at->sortable();
  16. $grid->filter(function (Grid\Filter $filter) {
  17. $filter->like('slug');
  18. $filter->like('name');
  19. $filter->like('http_path');
  20. });
  21. });
  22. }
  23. }

上面的代码执行的 sql 如下(默认只查询 parent = 0 的数据):

  1. select count(*) as aggregate from `demo_categories` where `parent_id` = 0
  2. select * from `demo_categories` where `parent_id` = 0 order by `order` asc, `id` asc limit 20 offset 0

Grid\Column::tree 方法参数

  • bool $showAll false 是否一次性展示下一层级的所有节点,默认分页展示
  • bool $sortable true 是否开启排序功能
  1. // 禁用分页功能,一次性加载所有下一层级节点
  2. $grid->title->tree(true);
  3. // 不需要 order 字段排序,第二个参数传 false 即可
  4. $grid->title->tree(false, false);

orderable排序

orderable 排序功能依赖 spatie/eloquent-sortable 组件,需要修改模型:

  1. use Spatie\EloquentSortable\Sortable;
  2. class Category extends Model implements Sortable
  3. {
  4. use ModelTree;
  5. // 设置排序字段,默认order
  6. protected $orderColumn = 'sort';
  7. }

下面是使用示例

  1. class CategoryController extends AdminController
  2. {
  3. protected function grid()
  4. {
  5. return Grid::make(new Category(), function (Grid $grid) {
  6. $grid->id('ID')->bold()->sortable();
  7. $grid->title->tree(); // 开启树状表格功能
  8. $grid->order->orderable(); // 开启排序功能
  9. ...;
  10. });
  11. }
  12. }

关于数据搜索

如果在树状表格中使用了搜索功能(Grid::filterGrid\Column::filterGrid::quickSearch),为了让用户能搜索到想要的数据,则会取消只查最顶级数据的操作

{tip} 使用 查询过滤列过滤器快捷搜索 等搜索功能都会取消只查最顶级数据的操作,只有 筛选器范围查询scope 等功能例外。

例如下面的代码开启了快捷搜索

  1. class CategoryController extends AdminController
  2. {
  3. protected function grid()
  4. {
  5. return Grid::make(new Category(), function (Grid $grid) {
  6. $grid->id('ID')->bold()->sortable();
  7. $grid->title->tree(); // 开启树状表格功能
  8. $grid->order->orderable(); // 开启排序功能
  9. $grid->quickSearch(['id', 'title']);
  10. ...;
  11. });
  12. }
  13. }

且用户在浏览器中使用了快捷搜索,则产生sql如下

  1. select count(*) as aggregate from `demo_categories` where `id` like "%xxx%" or `title` like "%xxx%"
  2. select * from `demo_categories` where `id` like "%xxx%" or `title` like "%xxx%" order by `order` asc, `id` asc limit 20 offset 0

与模型树功能的差别

模型树同样可用于展示多层级结构数据,并且支持用拖拽的方式实现数据的层级、排序等操作,但是不支持分页和点击加载功能,只能一次性加载完所有数据, 因此模型树并不适合用来展示数据量较大的数据。

而树状表格支持分页和点击加载功能,适合用来展示数据量较大的多层级结构数据,但不支持用拖拽的方式实现数据的层级、排序操作。