数据仓库

数据仓库(Repository)是Dcat Admin中对数据增删改查操作接口的具体实现,通过Repository的介入可以让页面的构建不再关心数据读写功能的具体实现,开发者通过实现Repository接口即可对数据进行读写操作。

{tip} 当然为了方便系统也保留了直接使用 Model 的功能,底层会自动把Model转化为数据仓库实例,毕竟大多数时候直接使用 Model 也能满足我们的需求。

数据表格Grid、数据表单Form、数据详情ShowTree 等组件不再直接依赖于Model,而是依赖于提供更简单清晰的接口的数据仓库,下面是Repository的所有接口:

  1. <?php
  2. namespace Dcat\Admin\Contracts;
  3. use Dcat\Admin\Form;
  4. use Dcat\Admin\Grid;
  5. use Dcat\Admin\Show;
  6. use Illuminate\Support\Collection;
  7. interface Repository
  8. {
  9. /**
  10. * 获取主键名称.
  11. *
  12. * @return string
  13. */
  14. public function getKeyName();
  15. /**
  16. * 获取创建时间字段.
  17. *
  18. * @return string
  19. */
  20. public function getCreatedAtColumn();
  21. /**
  22. * 获取更新时间字段.
  23. *
  24. * @return string
  25. */
  26. public function getUpdatedAtColumn();
  27. /**
  28. * 是否使用软删除.
  29. *
  30. * @return bool
  31. */
  32. public function isSoftDeletes();
  33. /**
  34. * 获取Grid表格数据.
  35. *
  36. * @param Grid\Model $model
  37. *
  38. * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator|Collection|array
  39. */
  40. public function get(Grid\Model $model);
  41. /**
  42. * 获取编辑页面数据.
  43. *
  44. * @param Form $form
  45. *
  46. * @return array|\Illuminate\Contracts\Support\Arrayable
  47. */
  48. public function edit(Form $form);
  49. /**
  50. * 获取详情页面数据.
  51. *
  52. * @param Show $show
  53. *
  54. * @return array|\Illuminate\Contracts\Support\Arrayable
  55. */
  56. public function detail(Show $show);
  57. /**
  58. * 新增记录.
  59. *
  60. * @param Form $form
  61. *
  62. * @return mixed
  63. */
  64. public function store(Form $form);
  65. /**
  66. * 查询更新前的行数据.
  67. *
  68. * @param Form $form
  69. *
  70. * @return array|\Illuminate\Contracts\Support\Arrayable
  71. */
  72. public function updating(Form $form);
  73. /**
  74. * 更新数据.
  75. *
  76. * @param Form $form
  77. *
  78. * @return bool
  79. */
  80. public function update(Form $form);
  81. /**
  82. * 删除数据.
  83. *
  84. * @param Form $form
  85. * @param array $deletingData
  86. *
  87. * @return mixed
  88. */
  89. public function delete(Form $form, array $deletingData);
  90. /**
  91. * 查询删除前的行数据.
  92. *
  93. * @param Form $form
  94. *
  95. * @return array|\Illuminate\Contracts\Support\Arrayable
  96. */
  97. public function deleting(Form $form);
  98. }

如果你的数据是多层级结构,则还需要实现以下接口

  1. <?php
  2. namespace Dcat\Admin\Contracts;
  3. interface TreeRepository
  4. {
  5. /**
  6. * 获取主键字段名称.
  7. *
  8. * @return string
  9. */
  10. public function getPrimaryKeyColumn();
  11. /**
  12. * 获取父级ID字段名称.
  13. *
  14. * @return string
  15. */
  16. public function getParentColumn();
  17. /**
  18. * 获取标题字段名称.
  19. *
  20. * @return string
  21. */
  22. public function getTitleColumn();
  23. /**
  24. * 获取排序字段名称.
  25. *
  26. * @return string
  27. */
  28. public function getOrderColumn();
  29. /**
  30. * 保存层级数据排序.
  31. *
  32. * @param array $tree
  33. * @param int $parentId
  34. */
  35. public function saveOrder($tree = [], $parentId = 0);
  36. /**
  37. * 设置数据查询回调.
  38. *
  39. * @param \Closure|null $query
  40. *
  41. * @return $this
  42. */
  43. public function withQuery($queryCallback);
  44. /**
  45. * 获取层级数据.
  46. *
  47. * @return array
  48. */
  49. public function toTree();
  50. }

Repository接口

getKeyName

此接口要求返回数据的主键字段名称,需要返回string类型值。

  1. public function getKeyName()
  2. {
  3. return 'id';
  4. }

getCreatedAtColumn

此接口要求返回数据的created_at字段名称,如果没有值可以返回空字符串或null值。

  1. // 如果没有值可以返回空字符串或`null`值
  2. public function getCreatedAtColumn()
  3. {
  4. return 'created_at';
  5. }

getUpdatedAtColumn

此接口要求返回数据的updated_at字段名称,如果没有值可以返回空字符串或null值。

  1. // 如果没有值可以返回空字符串或`null`值
  2. public function getCreatedAtColumn()
  3. {
  4. return 'updated_at';
  5. }

isSoftDeletes

此接口要求返回数据是否支持软删除,请返回一个bool类型的值。

  1. public function isSoftDeletes()
  2. {
  3. return true;
  4. }

get

此接口要求返回数据表格Grid的数据,用于数据表格展示,要求返回一个arrayIlluminate\Support\CollectionLengthAwarePaginator类型值。

分页

当数据需要分页时要求返回一个\Illuminate\Contracts\Pagination\LengthAwarePaginator类型值:

  1. public function get(Grid\Model $model)
  2. {
  3. // 获取当前页数
  4. $currentPage = $model->getCurrentPage();
  5. // 获取每页显示行数
  6. $perPage = $model->getPerPage();
  7. // 获取筛选参数
  8. $city = $model->filter()->input(Grid\Filter\Scope::QUERY_NAME, '广州');
  9. $start = ($currentPage - 1) * $perPage;
  10. $client = new \GuzzleHttp\Client();
  11. $response = $client->get("{$this->api}?{$this->apiKey}&city=$city&start=$start&count=$perPage");
  12. $data = json_decode((string)$response->getBody(), true);
  13. return $model->makePaginator(
  14. $data['total'] ?? 0, // 传入总记录数
  15. $data['subjects'] ?? [] // 传入数据二维数组
  16. );
  17. }

不分页

如果不需要分页,则直接返回一个arrayIlluminate\Support\Collection类型值即可。

  1. public function get(Grid\Model $model)
  2. {
  3. return [
  4. ['id' => 1, 'name' => 'n1'],
  5. ['id' => 2, 'name' => 'n2']
  6. ];
  7. }

注意,grid需要禁用分页

  1. $grid->disablePagination()

edit

此接口要求返回表单编辑页面的数据,用于显示数据表单编辑页面,需要返回array类型值。

  1. public function edit(Form $form): array
  2. {
  3. // 获取数据主键值
  4. $id = $form->getKey();
  5. return ['id' => 1, 'name' => 'n1'];
  6. }

detail

此接口要求返回数据详情页面的数据,用于显示数据详情,需要返回array类型值。

  1. public function detail(Show $show): array
  2. {
  3. // 获取数据主键值
  4. $id = $show->getId();
  5. return ['id' => 1, 'name' => 'n1'];
  6. }

store

此接口用于新增一条记录,可以返回intstringbool类型值。

  1. public function store(Form $form)
  2. {
  3. // 获取待新增的数据
  4. $attributes = $form->updates();
  5. // 执行你的新增逻辑
  6. // 返回新增记录id或bool值
  7. return 1;
  8. }

updating

此接口用于数据表单修改数据时查询原始记录,需要返回arrayModel类型值。

{tip} 此接口只有某些特殊字段会用到,如图片、文件上传字段,当更改了图片或文件时可以根据这个接口查出的数据删除旧文件。所以如果你的表单中没有用到此类特殊字段,此接口可以返回一个空数组。

  1. public function updating(Form $form)
  2. {
  3. // 获取数据主键值
  4. $id = $form->getKey();
  5. return ['id' => 1, 'name' => 'n1'];
  6. }

update

此接口用于数据表单修改记录,可以返回intstringbool类型值。

  1. public function update(Form $form)
  2. {
  3. // 获取待编辑的数据
  4. $attributes = $form->updates();
  5. // 执行你的编辑逻辑
  6. // 返回成功
  7. return true;
  8. }

deleting

此接口用于删除数据时查询原始记录,需要返回二维数组,或Collection model。

  1. public function deleting(Form $form): array
  2. {
  3. // 当批量删除时id为多个
  4. $id = explode(',', $form->getKey());
  5. // 执行你的逻辑
  6. // 注意这里需要返回二维数组
  7. return [
  8. ['id' => 1, 'name' => 'h1'],
  9. ];
  10. // 也可以返回collection
  11. return Modell::find($id);
  12. }

destroy

单行/批量删除数据方法,成功返回true,失败返回false

  1. public function destroy(Form $form, array $deletingData)
  2. {
  3. // 当批量删除时id为多个
  4. $id = explode(',', $form->getKey());
  5. // $deletingData 是 getDataWhenDeleting 接口返回的数据
  6. // 执行你的逻辑
  7. return true;
  8. }

TreeRepository接口

getPrimaryKeyColumn

此接口用于返回数据的主键字段名称,需要返回string类型值。

  1. public function getPrimaryKeyColumn()
  2. {
  3. return $this->getKeyName();
  4. }

getParentColumn

此接口用于返回数据的父ID字段名称,需要返回string类型值。

  1. public function getParentColumn()
  2. {
  3. return 'parent_id';
  4. }

getTitleColumn

此接口用于返回数据标题字段名称,需要返回string类型值。

  1. public function getTitleColumn()
  2. {
  3. return 'title';
  4. }

getOrderColumn

此接口用于返回数据排序字段名称,需要返回string类型值。

{tip} 此字段不是必须的,如果你的数据不支持或不需要排序,请返回空值!

  1. public function getOrderColumn()
  2. {
  3. return 'order';
  4. }

saveOrder

此接口用于保存层级数据的排序,并且接收两个参数

  • $tree array 此字段是一个已分好层级的数组
  • $parentId int 此字段主要用于递归时传递父ID使用

{tip} 如果你的数据不支持 MySQL,可参考 Dcat\Admin\Traits\ModelTree::saveOrder 方法自行实现。

  1. $tree = [
  2. [
  3. 'id' => 1,
  4. 'title' => 'title',
  5. 'parent_id' => 0,
  6. 'children' => [
  7. [
  8. 'id' => 2,
  9. 'title' => 'child1',
  10. 'parent_id' => 1,
  11. ],
  12. [
  13. 'id' => 3,
  14. 'title' => 'child2',
  15. 'parent_id' => 1,
  16. ],
  17. ],
  18. ]
  19. ];
  20. // 保存排序,内层逻辑请自行实现
  21. $repository->saveOrder($tree);

withQuery

此接口需结合 toTree 接口使用,接收一个参数:主要用于设置数据查询操作的相关回调或参数。

  1. <?php
  2. use Dcat\Admin\Contracts\Repository;
  3. use Dcat\Admin\Contracts\TreeRepository;
  4. use Dcat\Admin\Support\Helper;
  5. class Category implements Repository, TreeRepository
  6. {
  7. protected $queryCallbacks = [];
  8. public function withQuery($queryCallback)
  9. {
  10. $this->queryCallbacks[] = $queryCallback;
  11. return $this;
  12. }
  13. public function toTree()
  14. {
  15. // 这里演示的代码只是为了说明 withQuery 方法的作用
  16. $client = ...;
  17. foreach ($this->queryCallbacks as $callback) {
  18. $callback($client);
  19. }
  20. return Helper::buildNestedArray($client->get());
  21. }
  22. }

toTree

此接口主要用于查询数据并分好层级返回,需要返回 array 类型值。

  1. public function toTree()
  2. {
  3. $client = ...;
  4. foreach ($this->queryCallbacks as $callback) {
  5. $callback($client);
  6. }
  7. return Helper::buildNestedArray($client->get());
  8. }

模型

Dcat Admin已经内置了对Eloquent model的支持,如果你的数据源是支持Model的,那么只需继承Dcat\Admin\Repositories\EloquentRepository类即可实现对数据的CURD操作,如:

  1. <?php
  2. namespace App\Admin\Repositories;
  3. use Dcat\Admin\Repositories\EloquentRepository;
  4. use App\Models\Movie as MovieModel;
  5. class Movie extends EloquentRepository
  6. {
  7. // 这里设置你的模型类名即可
  8. protected $eloquentClass = MovieModel::class;
  9. // 通过这个方法可以指定查询的字段,默认"*"
  10. public function getGridColumns()
  11. {
  12. return [$this->getKeyName(), 'name', 'title', 'created_at'];
  13. }
  14. // 通过这个方法可以指定表单页查询的字段,默认"*"
  15. public function getFormColumns()
  16. {
  17. return [$this->getKeyName(), 'name', 'title', 'created_at'];
  18. }
  19. // 通过这个方法可以指定数据详情页查询的字段,默认"*"
  20. public function getDetailColumns()
  21. {
  22. return ['*'];
  23. }
  24. }

QueryBuilder

如果你的数据支持QueryBuilder查询,但不方便建模型类(比如需要动态查表数据),则可以继承Dcat\Admin\Repositories\QueryBuilderRepository类。

{tip} 注意,QueryBuilderRepository默认是不支持Model的关联模型、软删除、模型树以及字段排序等功能,如果需要这些功能,请自定实现上述相关接口即可。

  1. <?php
  2. namespace App\Admin\Repositories;
  3. use Dcat\Admin\Repositories\QueryBuilderRepository;
  4. class MyRepository extends QueryBuilderRepository
  5. {
  6. // 设置你的主键名称
  7. protected $keyName = 'id';
  8. // 设置创建时间字段
  9. protected $createdAtColumn = 'created_at';
  10. // 设置更新时间字段
  11. protected $updatedAtColumn = 'updated_at';
  12. // 返回表名
  13. public function getTable()
  14. {
  15. return 'your_table_name';
  16. }
  17. // 返回你的主键名称
  18. public function getKeyName()
  19. {
  20. return $this->keyName;
  21. }
  22. // 通过这个方法可以指定查询的字段,默认"*"
  23. public function getGridColumns()
  24. {
  25. return [$this->getKeyName(), 'name', 'title', 'created_at'];
  26. }
  27. // 通过这个方法可以指定表单页查询的字段,默认"*"
  28. public function getFormColumns()
  29. {
  30. return [$this->getKeyName(), 'name', 'title', 'created_at'];
  31. }
  32. // 通过这个方法可以指定数据详情页查询的字段,默认"*"
  33. public function getDetailColumns()
  34. {
  35. return ['*'];
  36. }
  37. }