BaseDao.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. <?php
  2. /**
  3. * @author: liaofei<136327134@qq.com>
  4. * @day: 2020/7/6
  5. */
  6. namespace app\dao;
  7. use crmeb\basic\BaseModel;
  8. use think\exception\ValidateException;
  9. use think\helper\Str;
  10. use think\Model;
  11. /**
  12. * Class BaseDao
  13. * @package app\dao
  14. */
  15. abstract class BaseDao
  16. {
  17. /**
  18. * 当前表名别名
  19. * @var string
  20. */
  21. protected $alias;
  22. /**
  23. * join表别名
  24. * @var string
  25. */
  26. protected $joinAlis;
  27. /**
  28. * 获取当前模型
  29. * @return string
  30. */
  31. abstract protected function setModel(): string;
  32. /**
  33. * 设置join链表模型
  34. * @return string
  35. */
  36. protected function setJoinModel(): string
  37. {
  38. }
  39. /**
  40. * 读取数据条数
  41. * @param array $where
  42. * @return int
  43. */
  44. public function count(array $where = []): int
  45. {
  46. return $this->search($where)->count();
  47. }
  48. /**
  49. * 获取某些条件总数
  50. * @param array $where
  51. */
  52. public function getCount(array $where)
  53. {
  54. return $this->getModel()->where($where)->count();
  55. }
  56. /**
  57. * 获取某些条件去重总数
  58. * @param array $where
  59. * @param $field
  60. * @param $search
  61. */
  62. public function getDistinctCount(array $where, $field, $search = true)
  63. {
  64. if ($search) {
  65. return $this->search($where)->field('COUNT(distinct(' . $field . ')) as count')->select()->toArray()[0]['count'] ?? 0;
  66. } else {
  67. return $this->getModel()->where($where)->field('COUNT(distinct(' . $field . ')) as count')->select()->toArray()[0]['count'] ?? 0;
  68. }
  69. }
  70. /**
  71. * 获取模型
  72. * @return BaseModel
  73. */
  74. protected function getModel()
  75. {
  76. return app()->make($this->setModel());
  77. }
  78. /**
  79. * 获取主键
  80. * @return mixed
  81. */
  82. protected function getPk()
  83. {
  84. return $this->getModel()->getPk();
  85. }
  86. /**
  87. * 获取一条数据
  88. * @param int|array $id
  89. * @param array|null $field
  90. * @return array|Model|null
  91. * @throws \think\db\exception\DataNotFoundException
  92. * @throws \think\db\exception\DbException
  93. * @throws \think\db\exception\ModelNotFoundException
  94. */
  95. public function get($id, ?array $field = [], ?array $with = [])
  96. {
  97. if (is_array($id)) {
  98. $where = $id;
  99. } else {
  100. $where = [$this->getPk() => $id];
  101. }
  102. return $this->getModel()::where($where)->when(count($with), function ($query) use ($with) {
  103. $query->with($with);
  104. })->field($field ?? ['*'])->find();
  105. }
  106. /**
  107. * 查询一条数据是否存在
  108. * @param $map
  109. * @param string $field
  110. * @return bool 是否存在
  111. */
  112. public function be($map, string $field = '')
  113. {
  114. if (!is_array($map) && empty($field)) $field = $this->getPk();
  115. $map = !is_array($map) ? [$field => $map] : $map;
  116. return 0 < $this->getModel()->where($map)->count();
  117. }
  118. /**
  119. * 根据条件获取一条数据
  120. * @param array $where
  121. * @param string|null $field
  122. * @param array $with
  123. * @return array|Model|null
  124. * @throws \think\db\exception\DataNotFoundException
  125. * @throws \think\db\exception\DbException
  126. * @throws \think\db\exception\ModelNotFoundException
  127. */
  128. public function getOne(array $where, ?string $field = '*', array $with = [])
  129. {
  130. $field = explode(',', $field);
  131. return $this->get($where, $field, $with);
  132. }
  133. /**
  134. * 获取单个字段值
  135. * @param array $where
  136. * @param string|null $field
  137. * @return mixed
  138. */
  139. public function value(array $where, ?string $field = '')
  140. {
  141. $pk = $this->getPk();
  142. return $this->getModel()::where($where)->value($field ?: $pk);
  143. }
  144. /**
  145. * 获取某个字段数组
  146. * @param array $where
  147. * @param string $field
  148. * @param string $key
  149. * @return array
  150. */
  151. public function getColumn(array $where, string $field, string $key = '')
  152. {
  153. return $this->getModel()::where($where)->column($field, $key);
  154. }
  155. /**
  156. * 删除
  157. * @param int|string|array $id
  158. * @return mixed
  159. */
  160. public function delete($id, ?string $key = null)
  161. {
  162. if (is_array($id)) {
  163. $where = $id;
  164. } else {
  165. $where = [is_null($key) ? $this->getPk() : $key => $id];
  166. }
  167. return $this->getModel()::where($where)->delete();
  168. }
  169. /**
  170. * 更新数据
  171. * @param int|string|array $id
  172. * @param array $data
  173. * @return mixed
  174. */
  175. public function update($id, array $data, ?string $key = null)
  176. {
  177. if (is_array($id)) {
  178. $where = $id;
  179. } else {
  180. $where = [is_null($key) ? $this->getPk() : $key => $id];
  181. }
  182. return $this->getModel()::update($data, $where);
  183. }
  184. /**
  185. * 批量更新数据
  186. * @param array $ids
  187. * @param array $data
  188. * @param string|null $key
  189. * @return BaseModel
  190. */
  191. public function batchUpdate(array $ids, array $data, ?string $key = null)
  192. {
  193. return $this->getModel()::whereIn(is_null($key) ? $this->getPk() : $key, $ids)->update($data);
  194. }
  195. /**
  196. * 插入数据
  197. * @param array $data
  198. * @return mixed
  199. */
  200. public function save(array $data)
  201. {
  202. return $this->getModel()::create($data);
  203. }
  204. /**
  205. * 插入数据
  206. * @param array $data
  207. * @return mixed
  208. */
  209. public function saveAll(array $data)
  210. {
  211. return $this->getModel()::insertAll($data);
  212. }
  213. /**
  214. * 获取某个字段内的值
  215. * @param $value
  216. * @param string $filed
  217. * @param string $valueKey
  218. * @param array|string[] $where
  219. * @return mixed
  220. */
  221. public function getFieldValue($value, string $filed, ?string $valueKey = '', ?array $where = [])
  222. {
  223. return $this->getModel()->getFieldValue($value, $filed, $valueKey, $where);
  224. }
  225. /**
  226. * 获取搜索器和搜索条件key
  227. * @param array $withSearch
  228. * @return array[]
  229. * @throws \ReflectionException
  230. */
  231. private function getSearchData(array $withSearch)
  232. {
  233. $with = [];
  234. $whereKey = [];
  235. $respones = new \ReflectionClass($this->setModel());
  236. foreach ($withSearch as $fieldName) {
  237. $method = 'search' . Str::studly($fieldName) . 'Attr';
  238. if ($respones->hasMethod($method)) {
  239. $with[] = $fieldName;
  240. } else {
  241. $whereKey[] = $fieldName;
  242. }
  243. }
  244. return [$with, $whereKey];
  245. }
  246. /**
  247. * 根据搜索器获取搜索内容
  248. * @param array $withSearch
  249. * @param array|null $data
  250. * @return Model
  251. */
  252. protected function withSearchSelect(array $withSearch, ?array $data = [])
  253. {
  254. [$with] = $this->getSearchData($withSearch);
  255. return $this->getModel()->withSearch($with, $data);
  256. }
  257. /**
  258. * 搜索
  259. * @param array $where
  260. * @return \crmeb\basic\BaseModel|mixed
  261. */
  262. protected function search(array $where = [])
  263. {
  264. if ($where) {
  265. return $this->withSearchSelect(array_keys($where), $where);
  266. } else {
  267. return $this->getModel();
  268. }
  269. }
  270. /**
  271. * 求和
  272. * @param array $where
  273. * @param string $field
  274. * @param bool $search
  275. * @return float
  276. */
  277. public function sum(array $where, string $field, bool $search = false)
  278. {
  279. if ($search) {
  280. return $this->search($where)->sum($field);
  281. } else {
  282. return $this->getModel()::where($where)->sum($field);
  283. }
  284. }
  285. /**
  286. * 高精度加法
  287. * @param int|string $key
  288. * @param string $incField
  289. * @param string $inc
  290. * @param string|null $keyField
  291. * @param int $acc
  292. * @return bool
  293. * @throws \think\db\exception\DataNotFoundException
  294. * @throws \think\db\exception\DbException
  295. * @throws \think\db\exception\ModelNotFoundException
  296. */
  297. public function bcInc($key, string $incField, string $inc, string $keyField = null, int $acc = 2)
  298. {
  299. return $this->bc($key, $incField, $inc, $keyField, 1);
  300. }
  301. /**
  302. * 高精度 减法
  303. * @param int|string $uid id
  304. * @param string $decField 相减的字段
  305. * @param float|int $dec 减的值
  306. * @param string $keyField id的字段
  307. * @param bool $minus 是否可以为负数
  308. * @param int $acc 精度
  309. * @return bool
  310. */
  311. public function bcDec($key, string $decField, string $dec, string $keyField = null, int $acc = 2)
  312. {
  313. return $this->bc($key, $decField, $dec, $keyField, 2);
  314. }
  315. /**
  316. * 高精度计算并保存
  317. * @param $key
  318. * @param string $incField
  319. * @param string $inc
  320. * @param string|null $keyField
  321. * @param int $type
  322. * @param int $acc
  323. * @return bool
  324. * @throws \think\db\exception\DataNotFoundException
  325. * @throws \think\db\exception\DbException
  326. * @throws \think\db\exception\ModelNotFoundException
  327. */
  328. public function bc($key, string $incField, string $inc, string $keyField = null, int $type = 1, int $acc = 2)
  329. {
  330. if ($keyField === null) {
  331. $result = $this->get($key);
  332. } else {
  333. $result = $this->getOne([$keyField => $key]);
  334. }
  335. if (!$result) return false;
  336. if ($type === 1) {
  337. $new = bcadd($result[$incField], $inc, $acc);
  338. } else if ($type === 2) {
  339. if ($result[$incField] < $inc) return false;
  340. $new = bcsub($result[$incField], $inc, $acc);
  341. }
  342. $result->{$incField} = $new;
  343. return false !== $result->save();
  344. }
  345. /**
  346. * 减库存加销量
  347. * @param array $where
  348. * @param int $num
  349. * @return mixed
  350. */
  351. public function decStockIncSales(array $where, int $num, string $stock = 'stock', string $sales = 'sales')
  352. {
  353. $isQuota = false;
  354. if (isset($where['type']) && $where['type']) {
  355. $isQuota = true;
  356. if (count($where) == 2) {
  357. unset($where['type']);
  358. }
  359. }
  360. $field = $isQuota ? 'stock,quota' : 'stock';
  361. $product = $this->getModel()->where($where)->field($field)->find();
  362. if ($product) {
  363. $stockNum = $quotaNum = $num;
  364. if ($num > $product['stock']) {
  365. throw new ValidateException('商品库存不足');
  366. }
  367. if ($isQuota && $num > $product['quota']) {
  368. throw new ValidateException('商品库存不足');
  369. }
  370. return $this->getModel()->where($where)->when($isQuota, function ($query) use ($quotaNum) {
  371. $query->dec('quota', $quotaNum);
  372. })->dec($stock, $stockNum)->inc($sales, $num)->update();
  373. }
  374. return true;
  375. }
  376. /**
  377. * 加库存减销量
  378. * @param array $where
  379. * @param int $num
  380. * @return mixed
  381. */
  382. public function incStockDecSales(array $where, int $num, string $stock = 'stock', string $sales = 'sales')
  383. {
  384. $isQuota = false;
  385. if (isset($where['type']) && $where['type']) {
  386. $isQuota = true;
  387. if (count($where) == 2) {
  388. unset($where['type']);
  389. }
  390. }
  391. $salesOne = $this->getModel()->where($where)->value($sales);
  392. if ($salesOne) {
  393. $salesNum = $num;
  394. if ($num > $salesOne) {
  395. $salesNum = $salesOne;
  396. }
  397. return $this->getModel()->where($where)->when($isQuota, function ($query) use ($num) {
  398. $query->inc('quota', $num);
  399. })->inc($stock, $num)->dec($sales, $salesNum)->update();
  400. }
  401. return true;
  402. }
  403. }