DBCache.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. <?php
  2. namespace App\Model;
  3. use Cache;
  4. use Closure;
  5. use DateTime;
  6. use Illuminate\Pagination\Paginator;
  7. /**
  8. * 数据库模型 缓存读取
  9. *
  10. * Class DBCache
  11. * @package App\Model
  12. */
  13. class DBCache
  14. {
  15. protected $table = null;
  16. protected $attributes = [];
  17. protected $builder = null;
  18. private $__cache = true; //启用缓存(默认启用)
  19. private $__cacheMinutes = 1; //缓存时间(分钟, 默认1分钟)
  20. private $__removeCache = false; //删除缓存
  21. private $__join = [];
  22. private $__take = [];
  23. private $__where = [];
  24. private $__whereRaw = [];
  25. private $__whereIn = [];
  26. private $__select = [];
  27. private $__selectRaw = [];
  28. private $__orderBy = [];
  29. private $__orderByRaw = [];
  30. private $__inRandomOrder = false;
  31. public function __construct($tabel = null, array $attributes = [])
  32. {
  33. $this->initParameter();
  34. if ($tabel) {
  35. $this->table = $tabel;
  36. }
  37. if ($attributes) {
  38. $this->attributes = $attributes;
  39. }
  40. }
  41. public function setTable($table)
  42. {
  43. $this->table = $table;
  44. return $this;
  45. }
  46. public function setAttributes($attributes)
  47. {
  48. $this->attributes = $attributes;
  49. return $this;
  50. }
  51. /**
  52. * 是否缓存
  53. *
  54. * @param bool $isCache
  55. * @return $this
  56. */
  57. public function cache($isCache = true)
  58. {
  59. $this->__cache = $isCache ? true : false;
  60. return $this;
  61. }
  62. public function noCache()
  63. {
  64. $this->__cache = false;
  65. return $this;
  66. }
  67. /**
  68. * 缓存时间(分钟)
  69. *
  70. * @param $Minutes
  71. * @return $this
  72. */
  73. public function cacheMinutes($Minutes)
  74. {
  75. if ($Minutes === 'year') {
  76. $Minutes = 365 * 24 * 60;
  77. }elseif ($Minutes === 'month') {
  78. $Minutes = 30 * 24 * 60;
  79. }elseif ($Minutes === 'day') {
  80. $Minutes = 24 * 60;
  81. }elseif ($Minutes === 'hour') {
  82. $Minutes = 60;
  83. }
  84. if ($Minutes instanceof DateTime) {
  85. $this->__cacheMinutes = $Minutes;
  86. }else{
  87. $this->__cacheMinutes = max($Minutes, 1);
  88. }
  89. return $this;
  90. }
  91. /**
  92. * 删除缓存
  93. */
  94. public function removeCache()
  95. {
  96. $this->__removeCache = true;
  97. return $this;
  98. }
  99. public function forgetCache($cacheKey)
  100. {
  101. $this->__removeCache = false;
  102. return Cache::forget($cacheKey);
  103. }
  104. /* ******************************************************************************** */
  105. /* ******************************************************************************** */
  106. public function join($table, $first, $operator = null, $second = null, $type = 'inner', $where = false)
  107. {
  108. $this->__join[] = [
  109. $table,
  110. $first,
  111. $operator,
  112. $second,
  113. $type,
  114. $where
  115. ];
  116. return $this;
  117. }
  118. public function take($var)
  119. {
  120. $this->__take[] = $var;
  121. return $this;
  122. }
  123. public function where($column, $operator = null, $value = null, $boolean = 'and')
  124. {
  125. $this->__where[] = [
  126. $column,
  127. $operator,
  128. $value,
  129. $boolean
  130. ];
  131. return $this;
  132. }
  133. public function whereRaw($sql, $bindings = [], $boolean = 'and')
  134. {
  135. $this->__whereRaw[] = [
  136. $sql,
  137. $bindings,
  138. $boolean
  139. ];
  140. return $this;
  141. }
  142. public function whereIn($column, $values, $boolean = 'and', $not = false)
  143. {
  144. $this->__whereIn[] = [
  145. $column,
  146. $values,
  147. $boolean,
  148. $not
  149. ];
  150. return $this;
  151. }
  152. public function whereNotIn($column, $values, $boolean = 'and')
  153. {
  154. return $this->whereIn($column, $values, $boolean, true);
  155. }
  156. public function select($var = ['*'])
  157. {
  158. $this->__select[] = is_array($var) ? $var : func_get_args();
  159. return $this;
  160. }
  161. public function selectRaw($expression, array $bindings = [])
  162. {
  163. $this->__selectRaw[] = [
  164. $expression,
  165. $bindings
  166. ];
  167. return $this;
  168. }
  169. public function orderBy($column, $direction = 'asc')
  170. {
  171. $this->__orderBy[] = [
  172. $column,
  173. $direction
  174. ];
  175. return $this;
  176. }
  177. public function orderByDesc($column)
  178. {
  179. return $this->orderBy($column, 'desc');
  180. }
  181. public function orderByRaw($sql, $bindings = [])
  182. {
  183. $this->__orderByRaw[] = [
  184. $sql,
  185. $bindings
  186. ];
  187. return $this;
  188. }
  189. public function inRandomOrder($isRand = true)
  190. {
  191. $this->__inRandomOrder = $isRand?true:false;
  192. return $this;
  193. }
  194. /* ******************************************************************************** */
  195. /* ******************************************************************************** */
  196. /* ******************************************************************************** */
  197. /**
  198. * 初始化参数
  199. */
  200. private function initParameter() {
  201. $this->__cache = true;
  202. $this->__cacheMinutes = 1;
  203. $this->__removeCache = false;
  204. //
  205. $this->__join = [];
  206. $this->__take = [];
  207. $this->__where = [];
  208. $this->__whereRaw = [];
  209. $this->__whereIn = [];
  210. $this->__select = [];
  211. $this->__selectRaw = [];
  212. $this->__orderBy = [];
  213. $this->__orderByRaw = [];
  214. $this->__inRandomOrder = false;
  215. }
  216. /**
  217. * 获取缓存标识
  218. * @param string $type 查询方式
  219. * @param string $attach 附加标识
  220. * @return string
  221. */
  222. private function identify($type, $attach = '') {
  223. $identify = $this->addEncode($this->attributes);
  224. $identify.= $this->addEncode($this->__join);
  225. $identify.= $this->addEncode($this->__take);
  226. $identify.= $this->addEncode($this->__where);
  227. $identify.= $this->addEncode($this->__whereRaw);
  228. $identify.= $this->addEncode($this->__whereIn);
  229. $identify.= $this->addEncode($this->__select);
  230. $identify.= $this->addEncode($this->__selectRaw);
  231. $identify.= $this->addEncode($this->__orderBy);
  232. $identify.= $this->addEncode($this->__orderByRaw);
  233. $identify.= $this->addEncode($this->__inRandomOrder);
  234. $identify.= $this->addEncode($attach);
  235. //
  236. return 'DBCache:' . $this->table . ':' . $type . '::' . md5($identify);
  237. }
  238. private function addEncode($value)
  239. {
  240. $encodeName = '';
  241. if (is_array($value)) {
  242. sort($value);
  243. foreach ($value AS $key => $val) {
  244. $encodeName .= ':' . $key . '=' . $this->addEncode($val) . ';';
  245. }
  246. } elseif ($value instanceof Closure) {
  247. $join = new DBClause();
  248. call_user_func($value, $join);
  249. $encodeName .= ':' . $join->toString() . ';';
  250. } elseif (is_string($value) || is_numeric($value)) {
  251. $encodeName .= ':' . $value . ';';
  252. } else {
  253. $encodeName .= ':' . var_export($value, true) . ';';
  254. }
  255. return $encodeName;
  256. }
  257. /**
  258. * 创建对象
  259. * @return $this|DOModel|null
  260. */
  261. private function builder() {
  262. if ($this->builder === null) {
  263. $this->builder = new DOModel($this->table, $this->attributes);
  264. }
  265. $builder = $this->builder;
  266. //
  267. foreach ($this->__join AS $item) {
  268. $builder = $builder->join($item[0], $item[1], $item[2], $item[3], $item[4], $item[5]);
  269. }
  270. foreach ($this->__take AS $item) {
  271. $builder = $builder->take($item);
  272. }
  273. foreach ($this->__where AS $item) {
  274. $builder = $builder->where($item[0], $item[1], $item[2], $item[3]);
  275. }
  276. foreach ($this->__whereRaw AS $item) {
  277. $builder = $builder->whereRaw($item[0], $item[1], $item[2]);
  278. }
  279. foreach ($this->__whereIn AS $item) {
  280. $builder = $builder->whereIn($item[0], $item[1], $item[2], $item[3]);
  281. }
  282. foreach ($this->__select AS $item) {
  283. $builder = $builder->select($item);
  284. }
  285. foreach ($this->__selectRaw AS $item) {
  286. $builder = $builder->selectRaw($item[0], $item[1]);
  287. }
  288. foreach ($this->__orderBy AS $item) {
  289. $builder = $builder->orderBy($item[0], $item[1]);
  290. }
  291. foreach ($this->__orderByRaw AS $item) {
  292. $builder = $builder->orderByRaw($item[0], $item[1]);
  293. }
  294. if ($this->__inRandomOrder) {
  295. $builder = $builder->inRandomOrder();
  296. }
  297. //
  298. $this->initParameter();
  299. return $builder;
  300. }
  301. /* ******************************************************************************** */
  302. /* ******************************************************************************** */
  303. /* ******************************************************************************** */
  304. /**
  305. * 静态方法
  306. *
  307. * @param string $tabel
  308. * @return DBCache
  309. */
  310. public static function table($tabel = '')
  311. {
  312. return new DBCache($tabel);
  313. }
  314. /**
  315. * 获取一条数据
  316. *
  317. * @param array $columns
  318. * @return mixed
  319. */
  320. public function first($columns = ['*'])
  321. {
  322. if ($this->__cache) {
  323. $cacheKey = $this->identify('first', $columns);
  324. if ($this->__removeCache) {
  325. return $this->forgetCache($cacheKey);
  326. }
  327. $result = Cache::remember($cacheKey, $this->__cacheMinutes, function() use ($columns) {
  328. return $this->builder()->first($columns);
  329. });
  330. }else{
  331. $result = $this->builder()->first($columns);
  332. }
  333. return isset($result->original)?$result->original:null;
  334. }
  335. /**
  336. * 获取所有数据
  337. *
  338. * @param array $columns
  339. * @return array|bool
  340. */
  341. public function get($columns = ['*'])
  342. {
  343. if ($this->__cache) {
  344. $cacheKey = $this->identify('get', $columns);
  345. if ($this->__removeCache) {
  346. return $this->forgetCache($cacheKey);
  347. }
  348. $result = Cache::remember($cacheKey, $this->__cacheMinutes, function() use ($columns) {
  349. return $this->builder()->get($columns);
  350. });
  351. }else{
  352. $result = $this->builder()->get($columns);
  353. }
  354. //
  355. $array = [];
  356. foreach ($result AS $key=>$item) {
  357. $array[$key] = isset($item->original)?$item->original:null;
  358. }
  359. return $array;
  360. }
  361. /**
  362. * 查询结果的计数
  363. *
  364. * @param string $columns
  365. * @return int|bool
  366. */
  367. public function count($columns = '*')
  368. {
  369. if ($this->__cache) {
  370. $cacheKey = $this->identify('count', $columns);
  371. if ($this->__removeCache) {
  372. return $this->forgetCache($cacheKey);
  373. }
  374. $result = Cache::remember($cacheKey, $this->__cacheMinutes, function() use ($columns) {
  375. return $this->builder()->count($columns);
  376. });
  377. }else{
  378. $result = $this->builder()->count($columns);
  379. }
  380. return intval($result);
  381. }
  382. /**
  383. * 从查询的第一个结果中获得一个列的值
  384. *
  385. * @param $column
  386. * @return mixed
  387. */
  388. public function value($column)
  389. {
  390. if ($this->__cache) {
  391. $cacheKey = $this->identify('value', $column);
  392. if ($this->__removeCache) {
  393. return $this->forgetCache($cacheKey);
  394. }
  395. $result = Cache::remember($cacheKey, $this->__cacheMinutes, function() use ($column) {
  396. $value = $this->builder()->value($column);
  397. return $value ? $value : '';
  398. });
  399. }else{
  400. $result = $this->builder()->value($column);
  401. }
  402. return $result;
  403. }
  404. /**
  405. * 统计输出
  406. *
  407. * @param $column
  408. * @return bool|mixed
  409. */
  410. public function sum($column)
  411. {
  412. if ($this->__cache) {
  413. $cacheKey = $this->identify('sum', $column);
  414. if ($this->__removeCache) {
  415. return $this->forgetCache($cacheKey);
  416. }
  417. $result = Cache::remember($cacheKey, $this->__cacheMinutes, function() use ($column) {
  418. $sum = $this->builder()->sum($column);
  419. return $sum ? $sum : 0;
  420. });
  421. }else{
  422. $result = $this->builder()->sum($column);
  423. }
  424. return $result;
  425. }
  426. /**
  427. * 获取分页数据
  428. * @param null $perPage
  429. * @param array $columns
  430. * @param string $pageName
  431. * @param null $page
  432. * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator|mixed
  433. */
  434. public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
  435. {
  436. if ($this->__cache) {
  437. $attach = $this->addEncode($perPage);
  438. $attach.= $this->addEncode($columns);
  439. $attach.= $this->addEncode($pageName);
  440. $attach.= $this->addEncode(Paginator::resolveCurrentPage($pageName));
  441. $cacheKey = $this->identify('paginate', $attach);
  442. if ($this->__removeCache) {
  443. return $this->forgetCache($cacheKey);
  444. }
  445. $result = Cache::remember($cacheKey, $this->__cacheMinutes, function() use ($perPage, $columns, $pageName, $page) {
  446. return $this->builder()->paginate($perPage, $columns, $pageName, $page);
  447. });
  448. }else{
  449. $result = $this->builder()->paginate($perPage, $columns, $pageName, $page);
  450. }
  451. $array = [];
  452. foreach ($result AS $key=>$item) {
  453. $array[$key] = isset($item->original)?$item->original:null;
  454. }
  455. return [
  456. "currentPage" => $result->currentPage(),
  457. "firstItem" => $result->firstItem(),
  458. "hasMorePages" => $result->hasMorePages(),
  459. "lastItem" => $result->lastItem(),
  460. "lastPage" => $result->lastPage(),
  461. "nextPageUrl" => $result->nextPageUrl(),
  462. "previousPageUrl" => $result->previousPageUrl(),
  463. "perPage" => $result->perPage(),
  464. "total" => $result->total(),
  465. "lists" => $array,
  466. ];
  467. }
  468. }