Pages.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. <?php
  2. namespace App\Models;
  3. use Illuminate\Http\Request;
  4. use Illuminate\Support\Facades\Log;
  5. use Illuminate\Support\Facades\Cache;
  6. class Pages
  7. {
  8. public $model; // Eloquent 模型
  9. public $request; // 请求对象
  10. public $beforeClosure; // 执行前的闭包
  11. public $afterClosure; // 执行后的闭包
  12. protected $useCache = false; // 缓存开关
  13. protected $cacheTTL = 3600; // 缓存过期时间,单位为秒,默认 1 小时
  14. /**
  15. * 构造函数接收模型和请求对象
  16. *
  17. * @param Request $request 请求对象
  18. * @param Object $model Eloquent 模型
  19. */
  20. public function __construct(Request $request, $model)
  21. {
  22. $this->request = $request;
  23. $this->model = $model;
  24. }
  25. /**
  26. * 设置是否使用缓存
  27. *
  28. * @param boolean $enabled 缓存开关
  29. * @param integer $ttl 缓存过期时间,单位为秒
  30. * @return void
  31. */
  32. public function withCache($enabled = true, $ttl = 3600)
  33. {
  34. $this->useCache = $enabled;
  35. $this->cacheTTL = $ttl; // 设置缓存过期时间
  36. return $this;
  37. }
  38. // 获取缓存的键
  39. private function getCacheKey()
  40. {
  41. // 获取分页参数,默认值为 1 和 10
  42. $page = $this->request->input('page', 1);
  43. $pageSize = $this->request->input('page_size', 10);
  44. // 获取请求路径
  45. $url = $this->request->url();
  46. // 将 URL 和分页参数拼接成缓存键
  47. return 'page_' . md5($url . '?' . http_build_query(['page' => $page, 'page_size' => $pageSize]));
  48. }
  49. /**
  50. * 关联查询
  51. *
  52. * @param array $relations 关联的模型:如 ['user', 'category']
  53. * @return void
  54. */
  55. public function withRelations(array $relations)
  56. {
  57. $this->model = $this->model->with($relations);
  58. return $this;
  59. }
  60. /**
  61. * 设置执行前操作的闭包
  62. *
  63. * @param callable $closure 闭包函数,$query 为模型对象
  64. * @return void
  65. */
  66. public function before(callable $closure)
  67. {
  68. $this->beforeClosure = function ($query) use ($closure) {
  69. // 添加全局过滤逻辑,比如按条件自动加 where
  70. // $query->where('status', 1);
  71. return call_user_func($closure, $query);
  72. };
  73. }
  74. /**
  75. * 设置执行后操作的闭包
  76. *
  77. * @param callable $closure 闭包函数,$data 为查询结果
  78. * @return void
  79. */
  80. public function after(callable $closure)
  81. {
  82. $this->afterClosure = function ($data) use ($closure) {
  83. // 添加全局处理逻辑,比如隐藏某些字段
  84. // $data->makeHidden('sale_price');
  85. return call_user_func($closure, $data);
  86. };
  87. }
  88. // 执行前操作
  89. private function beforeExecution()
  90. {
  91. if (is_callable($this->beforeClosure)) {
  92. $this->model = call_user_func($this->beforeClosure, $this->model);
  93. }
  94. }
  95. // 执行后操作
  96. private function afterExecution($data)
  97. {
  98. if (is_callable($this->afterClosure)) {
  99. return call_user_func($this->afterClosure, $data);
  100. }
  101. return $data;
  102. }
  103. // 获取分页数据
  104. public function paginate()
  105. {
  106. try {
  107. // 使用注入的 Request 对象获取分页参数
  108. $perPage = $this->request->input('page_size', 10); // 获取每页显示的数量,默认值为10
  109. $sortBy = $this->request->input('sort_by', 'id'); // 默认按 id 排序
  110. $sortOrder = $this->request->input('sort_order', 'desc'); // 默认升序排序
  111. $page_not = $this->request->input('page_not', false); // 是否不使用分页
  112. // 执行前操作
  113. $this->beforeExecution();
  114. // 不使用分页
  115. if ($page_not) {
  116. $dataList = $this->afterExecution($this->model->get());
  117. return response()->json([
  118. 'code' => 1,
  119. 'msg' => "请求成功",
  120. // 当前页的数据,实际的分页数据,是当前页展示的内容
  121. 'data' => $dataList,
  122. ], 200);
  123. }
  124. // 排序功能
  125. $tableName = $this->model->getModel()->getTable();
  126. $this->model->orderBy($tableName . "." . $sortBy, $sortOrder);
  127. // 如果开启了缓存,首先检查缓存是否存在
  128. if ($this->useCache && Cache::store('redis')->has($this->getCacheKey())) {
  129. // 从缓存中获取分页数据
  130. // Log::info('从缓存中获取分页数据'.$this->getCacheKey());
  131. $paginator = Cache::store('redis')->get($this->getCacheKey());
  132. } else {
  133. // 执行分页查询
  134. $paginator = $this->model->paginate($perPage);
  135. // $paginator = $this->model->paginate($perPage,['*'] ,'page_now'); // 自定义分页字段
  136. // 如果开启了缓存,则缓存查询结果
  137. if ($this->useCache) {
  138. Cache::store('redis')->put($this->getCacheKey(), $paginator, $this->cacheTTL);
  139. }
  140. }
  141. // 执行后操作
  142. $this->afterExecution($paginator);
  143. return response()->json([
  144. 'code' => 1,
  145. 'msg' => "请求成功",
  146. // 当前页的数据,实际的分页数据,是当前页展示的内容
  147. 'data' => $paginator->items(),
  148. 'page_info' => [
  149. // 当前页码,指示用户当前所在的页数
  150. 'page_now' => $paginator->currentPage(),
  151. // 总页数,表示所有数据分成多少页
  152. 'page_count' => $paginator->lastPage(),
  153. // 总记录数,表示所有数据的总数
  154. 'total_count' => $paginator->total(),
  155. // 每页的记录数,表示每一页显示的数据量
  156. 'page_size' => $paginator->perPage(),
  157. // 当前页的第一条记录的序号,指示该页显示的第一项数据是第几条记录
  158. // 'from' => $paginator->firstItem(),
  159. // 当前页的最后一条记录的序号,指示该页显示的最后一项数据是第几条记录
  160. // 'to' => $paginator->lastItem(),
  161. ]
  162. ], 200);
  163. } catch (\Exception $e) {
  164. Log::error('分页查询失败: ' . $e->getMessage());
  165. return response()->json([
  166. 'code' => 0,
  167. 'msg' => "请求失败",
  168. ], 400);
  169. }
  170. }
  171. }