BaseModel.php 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258
  1. <?php
  2. /// +----------------------------------------------------------------------
  3. // | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
  4. // +----------------------------------------------------------------------
  5. // | 版权所有 2017~2021 LARAVEL研发中心
  6. // +----------------------------------------------------------------------
  7. // | 官方网站: http://www.laravel.cn
  8. // +----------------------------------------------------------------------
  9. // | Author: laravel开发员 <laravel.qq.com>
  10. // +----------------------------------------------------------------------
  11. namespace App\Models;
  12. /**
  13. * 缓存基类
  14. * @author zongjl
  15. * @date 2019/5/23
  16. * Class BaseModel
  17. * @package App\Models
  18. */
  19. class BaseModel extends CacheModel
  20. {
  21. // 创建时间
  22. const CREATED_AT = 'create_time';
  23. // 更新时间
  24. const UPDATED_AT = 'update_time';
  25. // // 删除时间
  26. // const DELETED_AT = 'delete_time';
  27. // 默认使用时间戳戳功能
  28. public $timestamps = true;
  29. // 人员ID
  30. public $userId;
  31. // 人员信息
  32. public $userInfo;
  33. // 时间
  34. public $time;
  35. /**
  36. * 构造函数
  37. * @author zongjl
  38. * @date 2019/5/30
  39. */
  40. public function __construct()
  41. {
  42. $uinfo = env("userInfo");
  43. $this->userId = $uinfo['id'];
  44. $this->userInfo = $uinfo;
  45. $this->time = time();
  46. }
  47. /**
  48. * 获取当前时间
  49. * @return int 时间戳
  50. * @author zongjl
  51. * @date 2019/5/30
  52. */
  53. public function freshTimestamp()
  54. {
  55. return time();
  56. }
  57. /**
  58. * 避免转换时间戳为时间字符串
  59. * @param mixed $value 时间
  60. * @return mixed|string|null
  61. * @author zongjl
  62. * @date 2019/5/30
  63. */
  64. public function fromDateTime($value)
  65. {
  66. return $value;
  67. }
  68. /**
  69. * 获取时间戳格式
  70. * @return string 时间戳字符串格式
  71. * @author zongjl
  72. * @date 2019/5/30
  73. */
  74. public function getDateFormat()
  75. {
  76. return 'U';
  77. }
  78. /**
  79. * 添加或编辑
  80. * @param array $data 数据源
  81. * @param string $error 异常错误信息
  82. * @param bool $is_sql 是否打印SQL
  83. * @return number 返回受影响行数据ID
  84. * @author zongjl
  85. * @date 2019/5/23
  86. */
  87. public function edit($data = [], &$error = '', $is_sql = false)
  88. {
  89. $id = isset($data['id']) ? (int)$data['id'] : 0;
  90. if ($id) {
  91. if (isset($data['update_user']) && empty($data['update_user'])) {
  92. $data['update_user'] = $this->userId;
  93. }
  94. // 置空添加时间
  95. unset($data['create_time']);
  96. // 更新时间
  97. $data['update_time'] = time();
  98. } else {
  99. // 创建时间
  100. $data['create_time'] = time();
  101. // 置空更新时间
  102. unset($data['update_time']);
  103. if (isset($data['update_user']) && empty($data['create_user'])) {
  104. $data['create_user'] = $this->userId;
  105. }
  106. }
  107. // 格式化表数据
  108. $this->formatData($data, $id);
  109. // 注册打印SQL监听事件
  110. $this->getLastSql($is_sql);
  111. // 入库处理
  112. if ($id) {
  113. // 修改数据
  114. $result = $this->where('id', $id)->update($data);
  115. // 更新ID
  116. $rowId = $id;
  117. } else {
  118. // 新增数据
  119. $result = $this->insertGetId($data);
  120. // 新增ID
  121. $rowId = $result;
  122. }
  123. if ($result !== false) {
  124. // 重置缓存
  125. if ($this->is_cache) {
  126. $data['id'] = $rowId;
  127. $this->cacheReset($rowId, $data, $id);
  128. }
  129. }
  130. return $rowId;
  131. }
  132. /**
  133. * 格式化数据
  134. * @param array $data 数组数据
  135. * @param int $id 数据记录ID
  136. * @param string $table 数据表
  137. * @return array 格式化数据
  138. * @author zongjl
  139. * @date 2019/5/24
  140. */
  141. private function formatData(&$data = [], $id = 0, $table = '')
  142. {
  143. $data_arr = [];
  144. $tables = $table ? explode(",", $table) : array($this->getTable());
  145. $item_data = [];
  146. foreach ($tables as $table) {
  147. $temp_data = [];
  148. $table_fields_list = $this->getTableFields($table);
  149. foreach ($table_fields_list as $field => $fieldInfo) {
  150. if ($field == "id") {
  151. continue;
  152. }
  153. //对强制
  154. if (isset($data[$field])) {
  155. if ($fieldInfo['Type'] == "int") {
  156. $item_data[$field] = (int)$data[$field];
  157. } else {
  158. $item_data[$field] = (string)$data[$field];
  159. }
  160. }
  161. if (!isset($data[$field]) && in_array($field, array('update_time', 'create_time'))) {
  162. continue;
  163. }
  164. //插入数据-设置默认值
  165. if (!$id && !isset($data[$field])) {
  166. $item_data[$field] = $fieldInfo['Default'];
  167. }
  168. if (isset($item_data[$field])) {
  169. $temp_data[$field] = $item_data[$field];
  170. }
  171. }
  172. $data_arr[] = $temp_data;
  173. }
  174. $data = $item_data;
  175. return $data_arr;
  176. }
  177. /**
  178. * 获取数据表字段
  179. * @param string $table 数据表名
  180. * @return array 字段数组
  181. * @author zongjl
  182. * @date 2019/5/24
  183. */
  184. private function getTableFields($table = '')
  185. {
  186. $table = $table ? $table : $this->getTable();
  187. if (strpos($table, DB_PREFIX) === false) {
  188. $table = DB_PREFIX . $table;
  189. }
  190. $field_list = \DB::select("SHOW FIELDS FROM {$table}");
  191. $info_list = [];
  192. foreach ($field_list as $row) {
  193. // 对象转数组格式
  194. $item = object_array($row);
  195. if ((strpos($item['Type'], "int") === false) || (strpos($item['Type'], "bigint") !== false)) {
  196. $type = "string";
  197. $default = $item['Default'] ? $item['Default'] : "";
  198. } else {
  199. $type = "int";
  200. $default = $item['Default'] ? $item['Default'] : 0;
  201. }
  202. $info_list[$item['Field']] = array(
  203. 'Type' => $type,
  204. 'Default' => $default
  205. );
  206. }
  207. return $info_list;
  208. }
  209. /**
  210. * 删除数据
  211. * @param int $id 删除数据ID
  212. * @param bool $is_sql 是否打印SQL
  213. * @return bool 返回true或false
  214. * @author zongjl
  215. * @date 2019/5/23
  216. */
  217. public function drop($id, $is_sql = false, $force=false)
  218. {
  219. // 注册打印SQL监听事件
  220. $this->getLastSql($is_sql);
  221. $result = $this->where('id', $id)->update(['mark' => 0]);
  222. if ($result !== false && $this->is_cache) {
  223. // 清除旧数据
  224. $this->where(['mark'=> 0])->where(self::UPDATED_AT,'<=', time() - 7 * 24 * 3600)->delete();
  225. // 删除成功
  226. $this->cacheDelete($id);
  227. }
  228. return $result;
  229. }
  230. /**
  231. * 查询缓存信息
  232. * @param int $id 查询数据ID
  233. * @return string 返回查询结果
  234. * @author zongjl
  235. * @date 2019/5/23
  236. */
  237. public function getInfo($id)
  238. {
  239. // 获取参数(用户提取操作人信息)
  240. $arg_list = func_get_args();
  241. $flag = isset($arg_list[0]) ? $arg_list[0] : 0;
  242. // 获取缓存信息
  243. $info = $this->getCacheFunc("info", $id);
  244. if ($info) {
  245. // 获取系统人员缓存
  246. $adminModel = new UserModel();
  247. $adminAll = $adminModel->getAll([], false, true);
  248. // 添加人
  249. if (isset($info['create_user']) && !empty($info['create_user'])) {
  250. $info['create_user_name'] = $adminAll[$info['create_user']]['realname'];
  251. }
  252. // 添加时间
  253. if (!empty($info['create_time'])) {
  254. $info['create_time'] = datetime($info['create_time'], 'Y-m-d H:i:s');
  255. }
  256. // 更新人
  257. if (isset($info['update_user']) && !empty($info['update_user'])) {
  258. $info['update_user_name'] = $adminAll[$info['update_user']]['realname'];
  259. }
  260. // 更新时间
  261. if (!empty($info['update_time'])) {
  262. $info['update_time'] = datetime($info['update_time'], 'Y-m-d H:i:s');
  263. }
  264. // 格式化信息(预留扩展方法,可不用)
  265. if (method_exists($this, 'formatInfo')) {
  266. $info = $this->formatInfo($info);
  267. }
  268. }
  269. return $info;
  270. }
  271. /**
  272. * 格式化数据
  273. * @param array $info 实体数据对象
  274. * @return array 返回实体对象
  275. * @author zongjl
  276. * @date 2019/5/23
  277. */
  278. public function formatInfo($info)
  279. {
  280. // 基类方法可不做任何操作,在子类重写即可
  281. // TODO...
  282. return $info;
  283. }
  284. /**
  285. * 查询记录总数
  286. * @param array $map 查询条件(默认:数组格式)
  287. * @param string $fields 查询字段
  288. * @param bool $is_sql 是否打印SQL
  289. * @return int 返回记录总数
  290. * @author zongjl
  291. * @date 2019/5/23
  292. */
  293. public function getCount($map = [], $fields = null, $is_sql = false)
  294. {
  295. // 注册打印SQL监听事件
  296. $this->getLastSql($is_sql);
  297. // 必备查询条件
  298. $map[] = ['mark', '=', 1];
  299. // 闭包查询条件格式化
  300. $query = $this->formatQuery($this, $map);
  301. // 链式操作
  302. if ($fields) {
  303. $count = $query->count($fields);
  304. } else {
  305. $count = $query->count();
  306. }
  307. return (int)$count;
  308. }
  309. /**
  310. * 查询某个字段的求和值
  311. * @param array $map 查询条件(默认:数组)
  312. * @param string $field 求和字段
  313. * @param bool $is_sql 是否打印SQL
  314. * @return string 返回结果
  315. * @author zongjl
  316. * @date 2019/5/23
  317. */
  318. public function getSum($map = [], $field = '', $is_sql = false)
  319. {
  320. // 注册打印SQL监听事件
  321. $this->getLastSql($is_sql);
  322. // 必备查询条件
  323. $map[] = ['mark', '=', 1];
  324. // 闭包查询条件格式化
  325. $query = $this->formatQuery($this, $map);
  326. // 链式操作
  327. $result = $query->sum($field);
  328. return $result;
  329. }
  330. /**
  331. * 查询某个字段的最大值
  332. * @param array $map 查询条件(默认:数组)
  333. * @param string $field 查询字段
  334. * @param bool $is_sql 是否打印SQL
  335. * @return string 返回结果
  336. * @author zongjl
  337. * @date 2019/5/23
  338. */
  339. public function getMax($map = [], $field = '', $is_sql = false)
  340. {
  341. // 注册打印SQL监听事件
  342. $this->getLastSql($is_sql);
  343. // 必备查询条件
  344. $map[] = ['mark', '=', 1];
  345. // 闭包查询条件格式化
  346. $query = $this->formatQuery($this, $map);
  347. // 链式操作
  348. $result = $$query->max($field);
  349. return $result;
  350. }
  351. /**
  352. * 查询某个字段的最小值
  353. * @param array $map 查询条件(默认:数组)
  354. * @param string $field 查询字典
  355. * @param bool $is_sql 是否打印SQL
  356. * @return string 返回结果
  357. * @author zongjl
  358. * @date 2019/5/23
  359. */
  360. public function getMin($map = [], $field = '', $is_sql = false)
  361. {
  362. // 注册打印SQL监听事件
  363. $this->getLastSql($is_sql);
  364. // 必备查询条件
  365. $map[] = ['mark', '=', 1];
  366. // 闭包查询条件格式化
  367. $query = $this->formatQuery($this, $map);
  368. // 链式操作
  369. $result = $query->min($field);
  370. return $result;
  371. }
  372. /**
  373. * 查询某个字段的平均值
  374. * @param array $map 查询条件(默认:数组)
  375. * @param string $field 查询字段
  376. * @param bool $is_sql 是否打印SQL
  377. * @return string 返回结果
  378. * @author zongjl
  379. * @date 2019/5/23
  380. */
  381. public function getAvg($map = [], $field = '', $is_sql = false)
  382. {
  383. // 注册打印SQL监听事件
  384. $this->getLastSql($is_sql);
  385. // 必备查询条件
  386. $map[] = ['mark', '=', 1];
  387. // 闭包查询条件格式化
  388. $query = $this->formatQuery($this, $map);
  389. // 链式操作
  390. $result = $query->avg($field);
  391. return $result;
  392. }
  393. /**
  394. * 查询某个字段的单个值
  395. * @param array $map 查询条件(默认:数组)
  396. * @param string $field 查询字段
  397. * @param bool $is_sql 是否打印SQL
  398. * @return string 返回结果
  399. * @author zongjl
  400. * @date 2019/5/23
  401. */
  402. public function getValue($map = [], $field = 'id', $is_sql = false)
  403. {
  404. // 注册打印SQL监听事件
  405. $this->getLastSql($is_sql);
  406. // 必备查询条件
  407. $map[] = ['mark', '=', 1];
  408. // 闭包查询条件格式化
  409. $query = $this->formatQuery($this, $map);
  410. // 链式操作
  411. $result = $query->value($field);
  412. return $result;
  413. }
  414. /**
  415. * 查询单条数据
  416. * @param array $map 查询条件(默认:数组)
  417. * @param string $field 查询字段(默认:全部)
  418. * @param bool $is_sql 是否打印SQL
  419. * @return array 返回结果
  420. * @author zongjl
  421. * @date 2019/5/23
  422. */
  423. public function getOne($map = [], $field = '*', $is_sql = false)
  424. {
  425. // 注册打印SQL监听事件
  426. $this->getLastSql($is_sql);
  427. // 必备查询条件
  428. $map[] = ['mark', '=', 1];
  429. // 闭包查询条件格式化
  430. $query = $this->formatQuery($this, $map);
  431. // 分析字段
  432. if (!is_array($field) && strpos($field, ',')) {
  433. $field = explode(',', $field);
  434. }
  435. // 链式操作
  436. $result = $query->select($field)->first();
  437. // 对象转数组
  438. return $result ? $result->toArray() : [];
  439. }
  440. /**
  441. * 根据记录ID获取某一行的值
  442. * @param int $id 记录ID
  443. * @param string $field 指定字段(默认:所有字段)
  444. * @param bool $is_sql 是否打印SQL
  445. * @return array 返回结果
  446. * @author zongjl
  447. * @date 2019/5/23
  448. */
  449. public function getRow($id, $field = '*', $is_sql = false)
  450. {
  451. // 注册打印SQL监听事件
  452. $this->getLastSql($is_sql);
  453. // 分析字段
  454. if (!is_array($field) && strpos($field, ',')) {
  455. $field = explode(',', $field);
  456. }
  457. // 链式操作
  458. $result = $this->where('id', $id)->select($field)->first();
  459. // 对象转数组
  460. return $result ? $result->toArray() : [];
  461. }
  462. /**
  463. * 获取某一列的值
  464. * @param array $map 查询条件
  465. * @param string $field 字段
  466. * @param bool $is_sql 是否打印SQL
  467. * @return array 返回结果
  468. * @author zongjl
  469. * @date 2019/5/29
  470. */
  471. public function getColumn($map = [], $field = 'id', $is_sql = false)
  472. {
  473. // 注册打印SQL监听事件
  474. $this->getLastSql($is_sql);
  475. // 必备查询条件
  476. $map[] = ['mark', '=', 1];
  477. // 闭包查询条件格式化
  478. $query = $this->formatQuery($this, $map);
  479. // 链式操作
  480. $result = $query->pluck($field);
  481. // 对象转数组
  482. return $result ? $result->toArray() : [];
  483. }
  484. /**
  485. * 根据条件查询单条缓存记录
  486. * @param array $map 查询条件
  487. * @param array $fields 查询字段
  488. * @param array $sort 排序
  489. * @param int $id 记录ID
  490. * @return array 结果返回值
  491. * @author zongjl
  492. * @date 2019/5/29
  493. */
  494. public function getInfoByAttr($map = [], $fields = [], $sort = [['id', 'desc']], $id = 0)
  495. {
  496. // 必备查询条件
  497. $map[] = ['mark', '=', 1];
  498. // 排除主键
  499. if ($id) {
  500. $map[] = ['id', '!=', $id];
  501. }
  502. // 闭包查询条件格式化
  503. $query = $this->formatQuery($this, $map);
  504. // 排序(支持多重排序)
  505. $query = $query->when($sort, function ($query, $sort) {
  506. foreach ($sort as $v) {
  507. $query->orderBy($v[0], $v[1]);
  508. }
  509. });
  510. // 链式操作
  511. $result = $query->select('id')->first();
  512. $result = $result ? $result->toArray() : [];
  513. // 查询缓存
  514. $data = [];
  515. if ($result) {
  516. $info = $this->getInfo($result['id']);
  517. if ($info && !empty($fields)) {
  518. // 分析字段
  519. if (!is_array($fields) && strpos($fields, ',')) {
  520. $fields = explode(',', $fields);
  521. }
  522. foreach ($fields as $val) {
  523. $data[trim($val)] = $info[trim($val)];
  524. }
  525. unset($info);
  526. } else {
  527. $data = $info;
  528. }
  529. }
  530. return $data;
  531. }
  532. /**
  533. * 获取数据表
  534. * @return array 返回结果
  535. * @author zongjl
  536. * @date 2019/5/29
  537. */
  538. public function getTablesList()
  539. {
  540. $tables = [];
  541. $database = strtolower(env('DB_DATABASE'));
  542. $sql = 'SHOW TABLES';
  543. $list = \DB::select($sql);
  544. // 对象转数组
  545. $data = object_array($list);
  546. foreach ($data as $v) {
  547. if(isset($v["Tables_in_{$database}"]) && $v["Tables_in_{$database}"]){
  548. $tables[] = $v["Tables_in_{$database}"];
  549. }
  550. }
  551. return $tables;
  552. }
  553. /**
  554. * 检查表是否存在
  555. * @param string $table 数据表名
  556. * @return bool 返回结果:true存在,false不存在
  557. * @author zongjl
  558. * @date 2019/5/29
  559. */
  560. public function tableExists($table)
  561. {
  562. if (strpos($table, env('DB_PREFIX')) === false) {
  563. $table = env('DB_PREFIX') . $table;
  564. }
  565. $tables = $this->getTablesList();
  566. return in_array($table, $tables) ? true : false;
  567. }
  568. /**
  569. * 删除数据表
  570. * @param string $table 数据表名
  571. * @return mixed 结果返回值
  572. * @author zongjl
  573. * @date 2019/5/29
  574. */
  575. public function dropTable($table)
  576. {
  577. if (strpos($table, DB_PREFIX) === false) {
  578. $table = DB_PREFIX . $table;
  579. }
  580. return \DB::statement("DROP TABLE {$table}");
  581. }
  582. /**
  583. * 获取表字段
  584. * @param string $table 数据表名
  585. * @return array 字段数组
  586. * @author zongjl
  587. * @date 2019/5/29
  588. */
  589. public function getFieldsList($table)
  590. {
  591. if (strpos($table, DB_PREFIX) === false) {
  592. $table = DB_PREFIX . $table;
  593. }
  594. $fields = [];
  595. $list = \DB::select("SHOW COLUMNS FROM {$table}");
  596. // 对象转数组
  597. $data = object_array($list);
  598. foreach ($data as $v) {
  599. $fields[$v['Field']] = $v['Type'];
  600. }
  601. return $fields;
  602. }
  603. /**
  604. * 检查字段是否存在
  605. * @param string $table 数据表名
  606. * @param string $field 字段名
  607. * @return bool 返回结果true或false
  608. * @author zongjl
  609. * @date 2019/5/29
  610. */
  611. public function fieldExists($table, $field)
  612. {
  613. $fields = $this->getFieldsList($table);
  614. return array_key_exists($field, $fields);
  615. }
  616. /**
  617. * 插入数据(不存在缓存操作,请慎用)
  618. * @param array $data 数据源
  619. * @param bool $get_id 是否返回插入主键ID:true返回、false不返回
  620. * @return mixed 返回结果
  621. * @author zongjl
  622. * @date 2019/5/29
  623. */
  624. public function doInsert($data, $get_id = true)
  625. {
  626. if ($get_id) {
  627. // 插入数据并返回主键
  628. return $this->insertGetId($data);
  629. } else {
  630. // 返回影响数据的条数,没修改任何数据返回 0
  631. return $this->insert($data);
  632. }
  633. }
  634. /**
  635. * 更新数据(不存在缓存操作,请慎用)
  636. * @param array $data 数据源
  637. * @param array $where 更新条件
  638. * @param bool $is_sql
  639. * @return mixed 返回结果
  640. * @author zongjl
  641. * @date 2019/5/29
  642. */
  643. public function doUpdate($data, $where, $is_sql = false)
  644. {
  645. // 注册打印SQL监听事件
  646. $this->getLastSql($is_sql);
  647. // 闭包查询条件格式化
  648. $query = $this->formatQuery($this, $where);
  649. return $query->update($data);
  650. }
  651. /**
  652. * 删除数据(不存在缓存操作,请慎用)
  653. * @param array $where 查询条件
  654. * @param bool $is_sql 是否打印SQL
  655. * @return mixed 返回结果
  656. * @author zongjl
  657. * @date 2019/5/29
  658. */
  659. public function doDelete($where, $is_sql = false)
  660. {
  661. // 注册打印SQL监听事件
  662. $this->getLastSql($is_sql);
  663. // 闭包查询条件格式化
  664. $query = $this->formatQuery($this, $where);
  665. return $query->delete();
  666. }
  667. /**
  668. * 批量插入数据
  669. * @param array $data 数据源
  670. * @param bool $is_cache 是否设置缓存:true设置,false不设置
  671. * @return bool 返回结果true或false
  672. * @author zongjl
  673. * @date 2019/5/30
  674. */
  675. public function insertAll($data, $is_cache = true)
  676. {
  677. if (!is_array($data)) {
  678. return false;
  679. }
  680. if ($is_cache) {
  681. // 插入数据并设置缓存
  682. $num = 0;
  683. foreach ($data as $val) {
  684. $result = $this->edit($val);
  685. if ($result) {
  686. $num++;
  687. }
  688. }
  689. return $num ? true : false;
  690. } else {
  691. // 插入数据不设置缓存
  692. return $this->insert($data);
  693. }
  694. return false;
  695. }
  696. /**
  697. * 批量更新数据
  698. * @param array $data 数据源(备注,需要更新的数据对象中必须包含有效主键)
  699. * @param bool $is_cache 是否设置缓存:true设置,false不设置
  700. * @return bool 返回结果true或false
  701. * @author zongjl
  702. * @date 2019/5/30
  703. */
  704. public function saveAll($data, $is_cache = true)
  705. {
  706. if (!is_array($data)) {
  707. return false;
  708. }
  709. $num = 0;
  710. foreach ($data as $val) {
  711. if (!isset($val['id']) || empty($val['id'])) {
  712. continue;
  713. }
  714. if ($is_cache) {
  715. // 更新数据并设置缓存
  716. $result = $this->edit($val);
  717. } else {
  718. // 更新数据不设置缓存
  719. $id = $val['id'];
  720. unset($val['id']);
  721. $result = $this->where('id', $id)->update($val);
  722. }
  723. if ($result) {
  724. $num++;
  725. }
  726. }
  727. return $num ? true : false;
  728. }
  729. /**
  730. * 批量删除
  731. * @param array $data 删除记录ID(支持传入数组和逗号分隔ID字符串)
  732. * @param bool $is_force 是否物理删除,true物理删除false软删除
  733. * @return bool 返回结果true或false
  734. * @author zongjl
  735. * @date 2019/5/30
  736. */
  737. public function deleteAll($data, $is_force = false)
  738. {
  739. if (empty($data)) {
  740. return false;
  741. }
  742. if (!is_array($data)) {
  743. $data = explode(',', $data);
  744. }
  745. $num = 0;
  746. foreach ($data as $val) {
  747. if ($is_force) {
  748. // 物理删除
  749. $result = $this->where('id', $val)->delete();
  750. if ($result) {
  751. $this->cacheDelete($val);
  752. }
  753. } else {
  754. // 软删除
  755. $result = $this->drop($val);
  756. }
  757. if ($result) {
  758. $num++;
  759. }
  760. }
  761. return $num ? true : false;
  762. }
  763. /**
  764. * 获取数据列表【根据业务场景需要,封装的获取列表数据的常用方法】
  765. * @param array $map 查询条件
  766. * @param array $sort 排序(默认:id asc)
  767. * @param string $limit 限制条数
  768. * @param bool $is_sql 是否打印SQL
  769. * @return array 返回结果
  770. * @author zongjl
  771. * @date 2019/5/23
  772. */
  773. public function getList($map = [], $sort = [['id', 'asc']], $limit = '', $is_sql = false)
  774. {
  775. // 注册打印SQL监听事件
  776. $this->getLastSql($is_sql);
  777. // 必备查询条件
  778. $map[] = ['mark', '=', 1];
  779. // 闭包查询条件格式化
  780. $query = $this->formatQuery($this, $map);
  781. // 数据分页设置
  782. if ($limit) {
  783. list($offset, $page_size) = explode(',', $limit);
  784. $query = $query->offset($offset)->limit($page_size);
  785. }
  786. // 排序(支持多重排序)
  787. $query = $query->when($sort, function ($query, $sort) {
  788. foreach ($sort as $v) {
  789. $query->orderBy($v[0], $v[1]);
  790. }
  791. });
  792. // 查询数据并将对象转数组
  793. $result = $query->select('id')->get();
  794. $result = $result ? $result->toArray() : [];
  795. $list = [];
  796. if ($result) {
  797. foreach ($result as $val) {
  798. $info = $this->getInfo($val['id']);
  799. if (!$info) {
  800. continue;
  801. }
  802. $list[] = $info;
  803. }
  804. }
  805. return $list;
  806. }
  807. /**
  808. * 获取数据列表
  809. * @return array 返回结果
  810. * @author zongjl
  811. * @date 2019/5/27
  812. */
  813. public function getData()
  814. {
  815. // 获取参数
  816. $arg_list = func_get_args();
  817. // 查询参数
  818. $map = isset($arg_list[0]['query']) ? $arg_list[0]['query'] : [];
  819. // 排序
  820. $sort = isset($arg_list[0]['sort']) ? $arg_list[0]['sort'] : [['id', 'desc']];
  821. // 获取条数
  822. $limit = isset($arg_list[0]['limit']) ? $arg_list[0]['limit'] : '';
  823. // 回调方法名
  824. $func = isset($arg_list[1]) ? $arg_list[1] : "Short";
  825. // 自定义MODEL
  826. $model = isset($arg_list[2]) ? $arg_list[2] : $this;
  827. // 必备查询条件
  828. $map[] = ['mark', '=', 1];
  829. // 闭包查询条件格式化
  830. $query = $this->formatQuery($model, $map);
  831. // 排序(支持多重排序)
  832. $query = $query->when($sort, function ($query, $sort) {
  833. foreach ($sort as $v) {
  834. $query->orderBy($v[0], $v[1]);
  835. }
  836. });
  837. // 查询数据源
  838. if ($limit) {
  839. list($offset, $page_size) = explode(',', $limit);
  840. $query->offset($offset)->limit($page_size);
  841. } else {
  842. // TODO...
  843. }
  844. // 查询数据并转为数组
  845. $result = $query->select('id')->get();
  846. $result = $result ? $result->toArray() : [];
  847. $list = [];
  848. if (is_array($result)) {
  849. foreach ($result as $val) {
  850. $info = $model->getInfo($val['id']);
  851. if (!$info) {
  852. continue;
  853. }
  854. if (is_object($func)) {
  855. // 方法函数
  856. $data = $func($info);
  857. } else {
  858. // 直接返回
  859. $data = $info;
  860. }
  861. $list[] = $data;
  862. }
  863. }
  864. return $list;
  865. }
  866. /**
  867. * 获取数据列表
  868. * @return array 返回结果
  869. * @author zongjl
  870. * @date 2019/5/27
  871. */
  872. public function pageData()
  873. {
  874. // 获取参数
  875. $arg_list = func_get_args();
  876. // 查询参数
  877. $map = isset($arg_list[0]['query']) ? $arg_list[0]['query'] : [];
  878. // 排序
  879. $sort = isset($arg_list[0]['sort']) ? $arg_list[0]['sort'] : [['id', 'desc']];
  880. // 页码
  881. $page = isset($arg_list[0]['page']) ? $arg_list[0]['page'] : 1;
  882. // 每页数
  883. $perpage = isset($arg_list[0]['perpage']) ? $arg_list[0]['perpage'] : 20;
  884. // 回调方法名
  885. $func = isset($arg_list[1]) ? $arg_list[1] : "Short";
  886. // 自定义MODEL
  887. $model = isset($arg_list[2]) ? $arg_list[2] : $this;
  888. // 必备查询条件
  889. $map[] = ['mark', '=', 1];
  890. // 分页设置
  891. $start = ($page - 1) * $perpage;
  892. $limit = "{$start},{$perpage}";
  893. // 闭包查询条件格式化
  894. $query = $this->formatQuery($model, $map);
  895. // 查询总数
  896. $count = $query->count();
  897. // 排序(支持多重排序)
  898. $query = $query->when($sort, function ($query, $sort) {
  899. foreach ($sort as $v) {
  900. $query->orderBy($v[0], $v[1]);
  901. }
  902. });
  903. // 分页设置
  904. list($offset, $page_size) = explode(',', $limit);
  905. $result = $query->offset($offset)->limit($page_size)->select('id')->get();
  906. $result = $result ? $result->toArray() : [];
  907. $list = [];
  908. if (is_array($result)) {
  909. foreach ($result as $val) {
  910. $info = $model->getInfo($val['id']);
  911. if (!$info) {
  912. continue;
  913. }
  914. if (is_object($func)) {
  915. //方法函数
  916. $data = $func($info);
  917. } else {
  918. // 直接返回
  919. $data = $info;
  920. }
  921. $list[] = $data;
  922. }
  923. }
  924. // 返回结果
  925. $result = array(
  926. 'count' => $count,
  927. 'perpage' => $perpage,
  928. 'page' => $page,
  929. 'list' => $list,
  930. );
  931. return $result;
  932. }
  933. /**
  934. * 格式化查询条件
  935. * @param $model 模型
  936. * @param array $map 查询条件
  937. * @return mixed 返回结果
  938. * @author zongjl
  939. * @date 2019/5/30
  940. */
  941. public function formatQuery($model, $map)
  942. {
  943. $query = $model->where(function ($query) use ($map) {
  944. foreach ($map as $v) {
  945. if ($v instanceof \Closure) {
  946. $query = $query->where($v);
  947. continue;
  948. }
  949. // 判断是否是键值对类型
  950. if (key($v) !== 0) {
  951. $key = key($v);
  952. $val = $v[$key];
  953. $v = [$key, is_array($val) ? 'in' : '=', $val];
  954. }
  955. switch ($v[1]) {
  956. case 'like':
  957. // like查询
  958. if (strpos($v[0], '|') !== false) {
  959. $query->where(function ($query) use ($v) {
  960. $item = explode('|', $v[0]);
  961. foreach ($item as $vo) {
  962. $query->orWhere($vo, $v[1], $v[2]);
  963. }
  964. });
  965. } else {
  966. $query->where($v[0], $v[1], $v[2]);
  967. }
  968. break;
  969. case 'in':
  970. // in查询
  971. if (!is_array($v[2])) {
  972. $v[2] = explode(',', $v[2]);
  973. }
  974. $query->whereIn($v[0], $v[2]);
  975. break;
  976. case 'not in':
  977. // not in查询
  978. if (!is_array($v[2])) {
  979. $v[2] = explode(',', $v[2]);
  980. }
  981. $query->whereNotIn($v[0], $v[2]);
  982. break;
  983. case 'between':
  984. // between查询
  985. if (!is_array($v[2])) {
  986. $v[2] = explode(',', $v[2]);
  987. }
  988. $query->whereBetween($v[0], $v[2]);
  989. break;
  990. case 'not between':
  991. // not between查询
  992. if (!is_array($v[2])) {
  993. $v[2] = explode(',', $v[2]);
  994. }
  995. $query->whereNotBetween($v[0], $v[2]);
  996. break;
  997. case 'null':
  998. // null查询
  999. $query->whereNull($v[0]);
  1000. break;
  1001. case "not null":
  1002. // not null查询
  1003. $query->whereNotNull($v[0]);
  1004. break;
  1005. case "or":
  1006. // or查询
  1007. //格式:or (status=1 and status=2)
  1008. $where = $v[0];
  1009. $query->orWhere(function ($query) use ($where) {
  1010. // 递归解析查询条件
  1011. $this->formatQuery($query, $where);
  1012. });
  1013. break;
  1014. case 'xor':
  1015. // xor查询
  1016. // 格式:and (status=1 or status=2)
  1017. $where = $v[0];
  1018. $query->where(function ($query) use ($where) {
  1019. foreach ($where as $w) {
  1020. $query->orWhere(function ($query) use ($w) {
  1021. // 递归解析查询条件
  1022. $this->formatQuery($query, [$w]);
  1023. });
  1024. }
  1025. });
  1026. break;
  1027. default:
  1028. // 常规查询
  1029. if (count($v) == 2) {
  1030. $query->where($v[0], '=', $v[1]);
  1031. } else {
  1032. $query->where($v[0], $v[1], $v[2]);
  1033. }
  1034. break;
  1035. }
  1036. }
  1037. });
  1038. return $query;
  1039. }
  1040. /**
  1041. * 添加打印SQL语句监听事件
  1042. * @param bool $is_sql 是否打印SQL
  1043. * @author zongjl
  1044. * @date 2019/5/29
  1045. */
  1046. public function getLastSql($is_sql = false)
  1047. {
  1048. if ($is_sql) {
  1049. \DB::listen(function ($query) {
  1050. $bindings = $query->bindings;
  1051. $sql = $query->sql;
  1052. foreach ($bindings as $replace) {
  1053. $value = is_numeric($replace) ? $replace : "'" . $replace . "'";
  1054. $sql = preg_replace('/\?/', $value, $sql, 1);
  1055. }
  1056. echo $sql;
  1057. });
  1058. }
  1059. }
  1060. /**
  1061. * 开启事务
  1062. * @author zongjl
  1063. * @date 2019/5/30
  1064. */
  1065. public function startTrans()
  1066. {
  1067. // 事务-缓存相关处理
  1068. $GLOBALS['trans'] = true;
  1069. $transId = uniqid("trans_");
  1070. $GLOBALS['trans_id'] = $transId;
  1071. $GLOBALS['trans_keys'] = [];
  1072. $info = debug_backtrace();
  1073. $this->setCache($transId, $info[0]);
  1074. // 开启事务
  1075. \DB::beginTransaction();
  1076. }
  1077. /**
  1078. * 事务回滚
  1079. * @author zongjl
  1080. * @date 2019/5/30
  1081. */
  1082. public function rollBack()
  1083. {
  1084. // 事务回滚
  1085. \DB::rollBack();
  1086. // 回滚缓存处理
  1087. foreach ($GLOBALS['trans_keys'] as $key) {
  1088. $this->deleteCache($key);
  1089. }
  1090. $this->deleteCache($GLOBALS['trans_id']);
  1091. $GLOBALS['trans'] = false;
  1092. $GLOBALS['trans_keys'] = [];
  1093. }
  1094. /**
  1095. * 提交事务
  1096. * @author zongjl
  1097. * @date 2019/5/30
  1098. */
  1099. public function commit()
  1100. {
  1101. // 提交事务
  1102. \DB::commit();
  1103. // 事务缓存同步删除
  1104. $GLOBALS['trans'] = false;
  1105. $GLOBALS['trans_keys'] = [];
  1106. $this->deleteCache($GLOBALS['trans_id']);
  1107. }
  1108. /**
  1109. * 开启执行日志
  1110. * @author zongjl
  1111. * @date 2019/5/31
  1112. */
  1113. public function beginSQLLog()
  1114. {
  1115. \DB::connection()->enableQueryLog();
  1116. }
  1117. /**
  1118. * 结束日志并打印
  1119. * @author zongjl
  1120. * @date 2019/5/30
  1121. */
  1122. public function endSQLLog()
  1123. {
  1124. // 获取查询语句、参数和执行时间
  1125. $result = \DB::getLastSql();
  1126. if ($result) {
  1127. foreach ($result as &$val) {
  1128. $bindings = $val['bindings'];
  1129. $sql = $val['query'];
  1130. foreach ($bindings as $replace) {
  1131. $value = is_numeric($replace) ? $replace : "'" . $replace . "'";
  1132. $val['query'] = preg_replace('/\?/', $value, $sql, 1);
  1133. }
  1134. }
  1135. }
  1136. print_r($result);
  1137. exit;
  1138. }
  1139. }