DBCache.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  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. if ($sql === null) {
  136. return $this;
  137. }
  138. $this->__whereRaw[] = [
  139. $sql,
  140. $bindings,
  141. $boolean
  142. ];
  143. return $this;
  144. }
  145. public function whereIn($column, $values, $boolean = 'and', $not = false)
  146. {
  147. $this->__whereIn[] = [
  148. $column,
  149. $values,
  150. $boolean,
  151. $not
  152. ];
  153. return $this;
  154. }
  155. public function whereNotIn($column, $values, $boolean = 'and')
  156. {
  157. return $this->whereIn($column, $values, $boolean, true);
  158. }
  159. public function select($var = ['*'])
  160. {
  161. $this->__select[] = is_array($var) ? $var : func_get_args();
  162. return $this;
  163. }
  164. public function selectRaw($expression, array $bindings = [])
  165. {
  166. $this->__selectRaw[] = [
  167. $expression,
  168. $bindings
  169. ];
  170. return $this;
  171. }
  172. public function orderBy($column, $direction = 'asc')
  173. {
  174. $this->__orderBy[] = [
  175. $column,
  176. $direction
  177. ];
  178. return $this;
  179. }
  180. public function orderByDesc($column)
  181. {
  182. return $this->orderBy($column, 'desc');
  183. }
  184. public function orderByRaw($sql, $bindings = [])
  185. {
  186. $this->__orderByRaw[] = [
  187. $sql,
  188. $bindings
  189. ];
  190. return $this;
  191. }
  192. public function inRandomOrder($isRand = true)
  193. {
  194. $this->__inRandomOrder = $isRand?true:false;
  195. return $this;
  196. }
  197. /* ******************************************************************************** */
  198. /* ******************************************************************************** */
  199. /* ******************************************************************************** */
  200. /**
  201. * 初始化参数
  202. */
  203. private function initParameter() {
  204. $this->__cache = true;
  205. $this->__cacheMinutes = 1;
  206. $this->__removeCache = false;
  207. //
  208. $this->__join = [];
  209. $this->__take = [];
  210. $this->__where = [];
  211. $this->__whereRaw = [];
  212. $this->__whereIn = [];
  213. $this->__select = [];
  214. $this->__selectRaw = [];
  215. $this->__orderBy = [];
  216. $this->__orderByRaw = [];
  217. $this->__inRandomOrder = false;
  218. }
  219. /**
  220. * 获取缓存标识
  221. * @param string $type 查询方式
  222. * @param string $attach 附加标识
  223. * @return string
  224. */
  225. private function identify($type, $attach = '') {
  226. $identify = $this->addEncode($this->attributes);
  227. $identify.= $this->addEncode($this->__join);
  228. $identify.= $this->addEncode($this->__take);
  229. $identify.= $this->addEncode($this->__where);
  230. $identify.= $this->addEncode($this->__whereRaw);
  231. $identify.= $this->addEncode($this->__whereIn);
  232. $identify.= $this->addEncode($this->__select);
  233. $identify.= $this->addEncode($this->__selectRaw);
  234. $identify.= $this->addEncode($this->__orderBy);
  235. $identify.= $this->addEncode($this->__orderByRaw);
  236. $identify.= $this->addEncode($this->__inRandomOrder);
  237. $identify.= $this->addEncode($attach);
  238. //
  239. return 'DBCache:' . $this->table . ':' . $type . '::' . md5($identify);
  240. }
  241. private function addEncode($value)
  242. {
  243. $encodeName = '';
  244. if (is_array($value)) {
  245. sort($value);
  246. foreach ($value AS $key => $val) {
  247. $encodeName .= ':' . $key . '=' . $this->addEncode($val) . ';';
  248. }
  249. } elseif ($value instanceof Closure) {
  250. $join = new DBClause();
  251. call_user_func($value, $join);
  252. $encodeName .= ':' . $join->toString() . ';';
  253. } elseif (is_string($value) || is_numeric($value)) {
  254. $encodeName .= ':' . $value . ';';
  255. } else {
  256. $encodeName .= ':' . var_export($value, true) . ';';
  257. }
  258. return $encodeName;
  259. }
  260. /**
  261. * 创建对象
  262. * @return $this|DOModel|null
  263. */
  264. private function builder() {
  265. if ($this->builder === null) {
  266. $this->builder = new DOModel($this->table, $this->attributes);
  267. }
  268. $builder = $this->builder;
  269. //
  270. foreach ($this->__join AS $item) {
  271. $builder = $builder->join($item[0], $item[1], $item[2], $item[3], $item[4], $item[5]);
  272. }
  273. foreach ($this->__take AS $item) {
  274. $builder = $builder->take($item);
  275. }
  276. foreach ($this->__where AS $item) {
  277. $builder = $builder->where($item[0], $item[1], $item[2], $item[3]);
  278. }
  279. foreach ($this->__whereRaw AS $item) {
  280. $builder = $builder->whereRaw($item[0], $item[1], $item[2]);
  281. }
  282. foreach ($this->__whereIn AS $item) {
  283. $builder = $builder->whereIn($item[0], $item[1], $item[2], $item[3]);
  284. }
  285. foreach ($this->__select AS $item) {
  286. $builder = $builder->select($item);
  287. }
  288. foreach ($this->__selectRaw AS $item) {
  289. $builder = $builder->selectRaw($item[0], $item[1]);
  290. }
  291. foreach ($this->__orderBy AS $item) {
  292. $builder = $builder->orderBy($item[0], $item[1]);
  293. }
  294. foreach ($this->__orderByRaw AS $item) {
  295. $builder = $builder->orderByRaw($item[0], $item[1]);
  296. }
  297. if ($this->__inRandomOrder) {
  298. $builder = $builder->inRandomOrder();
  299. }
  300. //
  301. $this->initParameter();
  302. return $builder;
  303. }
  304. /* ******************************************************************************** */
  305. /* ******************************************************************************** */
  306. /* ******************************************************************************** */
  307. /**
  308. * 静态方法
  309. *
  310. * @param string $tabel
  311. * @return DBCache
  312. */
  313. public static function table($tabel = '')
  314. {
  315. return new DBCache($tabel);
  316. }
  317. /**
  318. * 获取一条数据
  319. *
  320. * @param array $columns
  321. * @return mixed
  322. */
  323. public function first($columns = ['*'])
  324. {
  325. if ($this->__cache) {
  326. $cacheKey = $this->identify('first', $columns);
  327. if ($this->__removeCache) {
  328. return $this->forgetCache($cacheKey);
  329. }
  330. $result = Cache::remember($cacheKey, $this->__cacheMinutes, function() use ($columns) {
  331. return $this->builder()->first($columns);
  332. });
  333. }else{
  334. $result = $this->builder()->first($columns);
  335. }
  336. return isset($result->original)?$result->original:null;
  337. }
  338. /**
  339. * 获取所有数据
  340. *
  341. * @param array $columns
  342. * @return array|bool
  343. */
  344. public function get($columns = ['*'])
  345. {
  346. if ($this->__cache) {
  347. $cacheKey = $this->identify('get', $columns);
  348. if ($this->__removeCache) {
  349. return $this->forgetCache($cacheKey);
  350. }
  351. $result = Cache::remember($cacheKey, $this->__cacheMinutes, function() use ($columns) {
  352. return $this->builder()->get($columns);
  353. });
  354. }else{
  355. $result = $this->builder()->get($columns);
  356. }
  357. //
  358. $array = [];
  359. foreach ($result AS $key=>$item) {
  360. $array[$key] = isset($item->original)?$item->original:null;
  361. }
  362. return $array;
  363. }
  364. /**
  365. * 查询结果的计数
  366. *
  367. * @param string $columns
  368. * @return int|bool
  369. */
  370. public function count($columns = '*')
  371. {
  372. if ($this->__cache) {
  373. $cacheKey = $this->identify('count', $columns);
  374. if ($this->__removeCache) {
  375. return $this->forgetCache($cacheKey);
  376. }
  377. $result = Cache::remember($cacheKey, $this->__cacheMinutes, function() use ($columns) {
  378. return $this->builder()->count($columns);
  379. });
  380. }else{
  381. $result = $this->builder()->count($columns);
  382. }
  383. return intval($result);
  384. }
  385. /**
  386. * 从查询的第一个结果中获得一个列的值
  387. *
  388. * @param $column
  389. * @return mixed
  390. */
  391. public function value($column)
  392. {
  393. if ($this->__cache) {
  394. $cacheKey = $this->identify('value', $column);
  395. if ($this->__removeCache) {
  396. return $this->forgetCache($cacheKey);
  397. }
  398. $result = Cache::remember($cacheKey, $this->__cacheMinutes, function() use ($column) {
  399. $value = $this->builder()->value($column);
  400. return $value ? $value : '';
  401. });
  402. }else{
  403. $result = $this->builder()->value($column);
  404. }
  405. return $result;
  406. }
  407. /**
  408. * 统计输出
  409. *
  410. * @param $column
  411. * @return bool|mixed
  412. */
  413. public function sum($column)
  414. {
  415. if ($this->__cache) {
  416. $cacheKey = $this->identify('sum', $column);
  417. if ($this->__removeCache) {
  418. return $this->forgetCache($cacheKey);
  419. }
  420. $result = Cache::remember($cacheKey, $this->__cacheMinutes, function() use ($column) {
  421. $sum = $this->builder()->sum($column);
  422. return $sum ? $sum : 0;
  423. });
  424. }else{
  425. $result = $this->builder()->sum($column);
  426. }
  427. return $result;
  428. }
  429. /**
  430. * 获取分页数据
  431. * @param null $perPage
  432. * @param array $columns
  433. * @param string $pageName
  434. * @param null $page
  435. * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator|mixed
  436. */
  437. public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
  438. {
  439. if ($this->__cache) {
  440. $attach = $this->addEncode($perPage);
  441. $attach.= $this->addEncode($columns);
  442. $attach.= $this->addEncode($pageName);
  443. $attach.= $this->addEncode(Paginator::resolveCurrentPage($pageName));
  444. $cacheKey = $this->identify('paginate', $attach);
  445. if ($this->__removeCache) {
  446. return $this->forgetCache($cacheKey);
  447. }
  448. $result = Cache::remember($cacheKey, $this->__cacheMinutes, function() use ($perPage, $columns, $pageName, $page) {
  449. return $this->builder()->paginate($perPage, $columns, $pageName, $page);
  450. });
  451. }else{
  452. $result = $this->builder()->paginate($perPage, $columns, $pageName, $page);
  453. }
  454. $array = [];
  455. foreach ($result AS $key=>$item) {
  456. $array[$key] = isset($item->original)?$item->original:null;
  457. }
  458. return [
  459. "currentPage" => $result->currentPage(),
  460. "firstItem" => $result->firstItem(),
  461. "hasMorePages" => $result->hasMorePages(),
  462. "lastItem" => $result->lastItem(),
  463. "lastPage" => $result->lastPage(),
  464. "nextPageUrl" => $result->nextPageUrl(),
  465. "previousPageUrl" => $result->previousPageUrl(),
  466. "perPage" => $result->perPage(),
  467. "total" => $result->total(),
  468. "lists" => $array,
  469. ];
  470. }
  471. }