Filter.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. <?php
  2. namespace App\Filters;
  3. use Carbon\Carbon;
  4. use Illuminate\Database\Eloquent\Builder;
  5. use Illuminate\Http\Request;
  6. use Illuminate\Support\Facades\Log;
  7. use Illuminate\Support\Str;
  8. abstract class Filter
  9. {
  10. protected $request;
  11. /**
  12. * @var Builder
  13. */
  14. protected $builder;
  15. protected $filters = [];
  16. protected $simpleFilters = [];
  17. public function __construct(Request $request)
  18. {
  19. $this->request = $request;
  20. $this->formatSimpleFilters();
  21. }
  22. /**
  23. * 把 simpleFilters 中没有指定过滤类型的, 自动改为 '='
  24. */
  25. protected function formatSimpleFilters()
  26. {
  27. $t = [];
  28. foreach ($this->simpleFilters as $field => $op) {
  29. if (is_int($field)) {
  30. $t[$op] = 'equal';
  31. } else {
  32. $t[$field] = $op;
  33. }
  34. }
  35. $this->simpleFilters = $t;
  36. }
  37. /**
  38. * 应用过滤
  39. *
  40. * @param $builder
  41. *
  42. * @return mixed
  43. */
  44. public function apply($builder)
  45. {
  46. $this->builder = $builder;
  47. foreach ($this->getFilters() as $filter => $value) {
  48. if (is_null($value)) {
  49. continue;
  50. }
  51. if ($op = $this->simpleFilters[$filter] ?? null) { // 简单过滤应用
  52. $this->applySimpleFilter($filter, $op, $value);
  53. } else { // 其他自定义过滤
  54. $method = Str::camel($filter);
  55. if (method_exists($this, $method)) {
  56. $this->$method($value);
  57. }
  58. }
  59. }
  60. return $this->builder;
  61. }
  62. /**
  63. * 过滤简单过滤器
  64. *
  65. * @param string $filter 过滤字段
  66. * @param string|array $op 操作
  67. * @param mixed $value 请求中对应的值
  68. */
  69. protected function applySimpleFilter($filter, $op, $value)
  70. {
  71. if (is_array($op)) {
  72. $args = array_slice($op, 1);
  73. $op = $op[0];
  74. }
  75. switch ($op) {
  76. case 'equal':
  77. $this->builder->where($filter, $value);
  78. break;
  79. case 'like':
  80. $this->builder->where($filter, 'like', str_replace('?', $value, $args[0]));
  81. break;
  82. case 'in':
  83. if (is_string($value)) {
  84. $value = explode(',', $value);
  85. }
  86. $this->builder->whereIn($filter, $value);
  87. break;
  88. case 'lt': // 小于
  89. $this->builder->where($filter, '<=', $value);
  90. break;
  91. case 'time_lt': // 小于时间 // 值必须为时间戳
  92. if ((int)$value < 10) {
  93. $time = Carbon::now()->subDays((int)$value)->format('Y-m-d H:i:s');
  94. $this->builder->where($filter, '<', $time);
  95. } else {
  96. $this->builder->where($filter, '<', date('Y-m-d H:i:s', $value));
  97. }
  98. break;
  99. case 'put_area': // 投放区域
  100. $this->builder->where('area_id', $value);
  101. break;
  102. case 'pay_time_between': // 支付时间区间筛选
  103. $this->builder->where('pay_time', '>', Carbon::parse($value[0])->format('Y-m-d H:i:s'))
  104. ->where('pay_time', '<', Carbon::parse($value[1])->format('Y-m-d H:i:s'));
  105. break;
  106. case 'created_time_between': // created_at时间区间筛选
  107. // Log::info($value);
  108. $this->builder->where(function ($q) use ($value) {
  109. $q->where('created_at', '>', Carbon::parse($value[0])->format('Y-m-d H:i:s'))
  110. ->where('created_at', '<', Carbon::parse($value[1])->format('Y-m-d H:i:s'));
  111. });
  112. break;
  113. default:
  114. // do nothing
  115. }
  116. }
  117. public function getFilters()
  118. {
  119. return $this->request->only(array_merge($this->filters, array_keys($this->simpleFilters)));
  120. }
  121. /**
  122. * 只保留特定的过滤字段
  123. *
  124. * @param array|string $only
  125. *
  126. * @return $this
  127. */
  128. public function only($only)
  129. {
  130. if (is_string($only)) {
  131. $only = [$only];
  132. }
  133. $this->filters = array_intersect($this->filters, $only);
  134. $this->simpleFilters = array_intersect($this->simpleFilters, $only);
  135. return $this;
  136. }
  137. }