心理咨询网
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447
  1. <?php
  2. /**
  3. * @copyright (C)2016-2099 Hnaoyun Inc.
  4. * @author XingMeng
  5. * @email hnxsh@foxmail.com
  6. * @date 2016年11月6日
  7. * 应用开发继承模型类
  8. */
  9. namespace core\basic;
  10. use core\basic\Config;
  11. use core\view\Paging;
  12. use core\database\Mysqli;
  13. use core\database\Sqlite;
  14. use core\database\Pdo;
  15. class Model
  16. {
  17. // 数据库表名
  18. public $table;
  19. // 表主键
  20. public $pk = 'id';
  21. // 是否自动设置时间戳
  22. public $autoTimestamp = false;
  23. // 是否数字时间戳格式
  24. public $intTimeFormat = false;
  25. // 更新时间字段名
  26. public $updateTimeField = 'update_time';
  27. // 创建时间字段名
  28. public $createTimeField = 'create_time';
  29. // 程序执行的SQL语句记录
  30. private $exeSql = array();
  31. // 是否解密转义
  32. private $decode = false;
  33. // 查询语句构建
  34. private $sql = array();
  35. // 直接显示SQL语句
  36. private $showSql = false;
  37. // 直接显示结果
  38. private $showRs = false;
  39. // 数据库驱动对象
  40. private $dbDriver;
  41. // 查询语句
  42. private $selectSql = "SELECT %distinct% %field% FROM %table% %join% %where% %group% %having% %order% %union% %limit%";
  43. // 计数语句
  44. private $countSql = "SELECT COUNT(*) AS sum FROM %table% %join% %where% %group% %having% %union%";
  45. private $countSql2 = "SELECT %distinct% %field% FROM %table% %join% %where% %group% %having% %union%";
  46. // 插入语句
  47. private $insertSql = "INSERT INTO %table% %field% VALUES %value%";
  48. // 多条插入语句
  49. private $insertMultSql = "INSERT INTO %table% %field% %value%";
  50. // 复制插入语句
  51. private $insertFromSql = "INSERT INTO %table% %field% %from%";
  52. // 删除语句
  53. private $deleteSql = "DELETE FROM %table% %join% %where%";
  54. // 更新语句
  55. private $updateSql = "UPDATE %table% SET %value% %join% %where%";
  56. // 查询索引
  57. private $checkIndex = "show index from %table%";
  58. // 自动表名
  59. public function __construct()
  60. {
  61. if (! $this->table) {
  62. $table_name = Config::get('database.prefix') . hump_to_underline(str_replace('Model', '', basename(get_called_class())));
  63. $this->table = $table_name;
  64. }
  65. }
  66. // 对象方式动态调用数据库操作方法
  67. public function __call($methed, $args)
  68. {
  69. if (method_exists($this->getDb(), $methed)) {
  70. $result = call_user_func_array(array(
  71. $this->getDb(),
  72. $methed
  73. ), $args);
  74. return $result;
  75. } else {
  76. error('不存在数据库操作方法“' . $methed . '”,请核对再试!');
  77. }
  78. }
  79. // 获取数据库连接对象
  80. private function getDb()
  81. {
  82. if (! $this->dbDriver) {
  83. $type = Config::get('database.type');
  84. switch ($type) {
  85. case 'mysqli': // 使用mysqli连接数据库
  86. $this->dbDriver = Mysqli::getInstance();
  87. break;
  88. case 'sqlite': // 使用sqlite连接数据库
  89. $this->dbDriver = Sqlite::getInstance();
  90. break;
  91. default: // 默认使用PDO连接数据库
  92. $this->dbDriver = Pdo::getInstance();
  93. }
  94. }
  95. return $this->dbDriver;
  96. }
  97. // 执行SQL构造替换
  98. private function buildSql($sql, $clear = true)
  99. {
  100. preg_match_all('/\%([\w]+)\%/', $sql, $matches);
  101. foreach ($matches[1] as $key => $value) {
  102. if (isset($this->sql[$value]) && $this->sql[$value]) {
  103. $sql = str_replace("%$value%", $this->sql[$value], $sql);
  104. } else {
  105. if ($value == 'table') {
  106. $sql = str_replace("%$value%", $this->table, $sql);
  107. } else {
  108. $sql = str_replace("%$value%", '', $sql);
  109. }
  110. }
  111. }
  112. $this->exeSql[] = $sql;
  113. if ($clear) {
  114. $this->pk = 'id';
  115. $this->autoTimestamp = false;
  116. $this->intTimeFormat = false;
  117. $this->updateTimeField = 'update_time';
  118. $this->createTimeField = 'create_time';
  119. $this->sql = array();
  120. }
  121. if ($this->showSql && $clear) {
  122. exit($sql);
  123. } else {
  124. return $sql;
  125. }
  126. }
  127. /**
  128. * 关闭自动提交,开启事务模式(非连贯,直接调用)
  129. */
  130. final public function begin()
  131. {
  132. $this->getDb()->begin();
  133. }
  134. /**
  135. * 提交事务(非连贯,直接调用)
  136. *
  137. * @return \core\basic\Model
  138. */
  139. final public function commit()
  140. {
  141. $this->getDb()->commit();
  142. }
  143. /**
  144. * 内容输出
  145. *
  146. * @param mixed $data
  147. * @return mixed
  148. */
  149. final protected function outData($result)
  150. {
  151. if ($this->decode) {
  152. $result = decode_string($result);
  153. $this->decode = false;
  154. } else {
  155. $result = decode_slashes($result);
  156. }
  157. if ($this->showRs) {
  158. print_r($result);
  159. exit();
  160. } else {
  161. return $result;
  162. }
  163. }
  164. /**
  165. * 连贯操作:是否解码转义数据
  166. */
  167. final public function decode($flag = true)
  168. {
  169. if ($flag === true)
  170. $this->decode = true;
  171. return $this;
  172. }
  173. /**
  174. * 连贯操作:设置返回SQL语句,不真正执行,优先级高于showRS()
  175. *
  176. * @param string $flag
  177. * 调用默认为true
  178. * @return \core\basic\Model
  179. */
  180. final public function showSql($flag = true)
  181. {
  182. if ($flag === true)
  183. $this->showSql = true;
  184. return $this;
  185. }
  186. /**
  187. * 连贯操作:设置显示结果到页面
  188. *
  189. * @param string $flag
  190. * 调用默认为true
  191. * @return \core\basic\Model
  192. */
  193. final public function showRs($flag = true)
  194. {
  195. if ($flag === true)
  196. $this->showRs = true;
  197. return $this;
  198. }
  199. /**
  200. * 连贯操作:是否自动插入时间
  201. *
  202. * @param string $flag
  203. * @return \core\basic\Model
  204. */
  205. final public function autoTime($flag = true)
  206. {
  207. if ($flag === true)
  208. $this->sql['auto_time'] = true;
  209. return $this;
  210. }
  211. /**
  212. * 连贯操作:设置查询表全名
  213. *
  214. * @param mixed $table
  215. * 可以是字符串、数组,
  216. * 字符串:如"ay_user as a",
  217. * 如传递多个表:array('ay_user','ay_role'),
  218. * 传递多个表并设置别名:array('ay_user'=>'u','ay_role'=>'r')
  219. * @return \core\basic\Model
  220. */
  221. final public function table($table)
  222. {
  223. if (is_array($table)) {
  224. $table_string = '';
  225. foreach ($table as $key => $value) {
  226. if (is_int($key)) {
  227. $table_string .= '`' . $value . '`,';
  228. } else {
  229. $table_string .= '`' . $key . '` AS ' . $value . ',';
  230. }
  231. }
  232. $this->sql['table'] = substr($table_string, 0, - 1);
  233. } else {
  234. $this->sql['table'] = $table;
  235. }
  236. return $this;
  237. }
  238. /**
  239. * 连贯操作:设置查询表名
  240. *
  241. * @param mixed $table
  242. * 可以是字符串、数组,
  243. * 字符串:如"user as a",
  244. * 如传递多个表:array('user','role'),
  245. * 传递多个表并设置别名:array('user'=>'u','role'=>'r')
  246. * @return \core\basic\Model
  247. */
  248. final public function name($table)
  249. {
  250. $prefix = Config::get('database.prefix');
  251. if (is_array($table)) {
  252. $table_string = '';
  253. foreach ($table as $key => $value) {
  254. if (is_int($key)) {
  255. $table_string .= '`' . $prefix . $value . '`,';
  256. } else {
  257. $table_string .= '`' . $prefix . $key . '` AS ' . $value . ',';
  258. }
  259. }
  260. $this->table = substr($table_string, 0, - 1);
  261. } else {
  262. $this->table = $prefix . $table;
  263. }
  264. return $this;
  265. }
  266. /**
  267. * 连贯操作:设置数据库别名
  268. *
  269. * @param string $alias
  270. * 设置的别名名字,接收字符串,如:a
  271. * @return \core\basic\Model
  272. */
  273. final public function alias($alias)
  274. {
  275. if ($alias) {
  276. if (! isset($this->table))
  277. error('调用alias之前必须先设置table');
  278. if (strpos($this->table, ' AS ') === false) {
  279. $this->table = $this->table . ' AS ' . $alias;
  280. }
  281. }
  282. return $this;
  283. }
  284. /**
  285. * 连贯操作:设置返回唯一不同的值
  286. *
  287. * @param string $flag
  288. * 调用时默认为true,如果传递false则不使用
  289. * @return \core\basic\Model
  290. */
  291. final public function distinct($flag = true)
  292. {
  293. if ($flag === true)
  294. $this->sql['distinct'] = 'DISTINCT';
  295. return $this;
  296. }
  297. /**
  298. * 连贯操作:设置字段
  299. *
  300. * @param mixed $field
  301. * 可以为字符串、数组,
  302. * 如字符串:"name,password as pw",
  303. * 数组设置字段:array('name','password'),如果为非数字数组则设置别名,
  304. * 数组设置字段并设置别名:array('username'=>'name','password'=>'pw')
  305. * @return \core\basic\Model
  306. */
  307. final public function field($field)
  308. {
  309. if (is_array($field)) {
  310. $field_string = '';
  311. foreach ($field as $key => $value) {
  312. if (is_int($key)) {
  313. $field_string .= $value . ',';
  314. } else {
  315. $field_string .= $key . ' AS ' . $value . ',';
  316. }
  317. }
  318. $this->sql['field'] = substr($field_string, 0, - 1);
  319. } elseif ($field) {
  320. $this->sql['field'] = $field;
  321. }
  322. return $this;
  323. }
  324. /**
  325. * 连贯操作:设置查询条件
  326. *
  327. * @param mixed $where
  328. * 设置条件,可以为字符串、数组,
  329. * 字符串模式:如"id<1","name like %1",
  330. * 数组模式:array('username'=>'xie',"realname like '%谢%'")
  331. * @param string $connect
  332. * 调用本方法时与前面条件使用AND连接,$where参数数组内部的条件默认使用AND连接
  333. * @return \core\basic\Model
  334. */
  335. /**
  336. * 连贯操作:设置查询条件
  337. *
  338. * @param mixed $where
  339. * 设置条件,可以为字符串、数组,
  340. * 字符串模式:如"id<1","name like %1",
  341. * 数组模式:array('username'=>'xie',"realname like '%谢%'")
  342. * @param string $inConnect
  343. * 调用本方法时$where参数数组内部的条件默认使用AND连接
  344. * @param string $outConnect
  345. * 调用本方法时与前面条件使用AND连接
  346. * @param boolean $fuzzy
  347. * 条件是否为模糊匹配,即in匹配
  348. * @return \core\basic\Model
  349. */
  350. final public function where($where, $inConnect = 'AND', $outConnect = 'AND', $fuzzy = false)
  351. {
  352. if (! $where) {
  353. return $this;
  354. }
  355. if (isset($this->sql['where']) && $this->sql['where']) {
  356. $this->sql['where'] .= ' ' . $outConnect . '(';
  357. } else {
  358. $this->sql['where'] = 'WHERE(';
  359. }
  360. if (is_array($where)) {
  361. $where_string = '';
  362. $flag = false;
  363. foreach ($where as $key => $value) {
  364. if ($flag) { // 条件之间内部AND连接
  365. $where_string .= ' ' . $inConnect . ' ';
  366. } else {
  367. $flag = true;
  368. }
  369. if (! is_int($key)) {
  370. if ($fuzzy) {
  371. $where_string .= $key . " like '%" . $value . "%' ";
  372. } else {
  373. $where_string .= $key . "='" . $value . "' ";
  374. }
  375. } else {
  376. $where_string .= $value;
  377. }
  378. }
  379. $this->sql['where'] .= $where_string . ')';
  380. } else {
  381. $this->sql['where'] .= $where . ')';
  382. }
  383. return $this;
  384. }
  385. /**
  386. * 连贯操作:设置EXISTS查询
  387. *
  388. * @param string $subsql
  389. * 传递子查询
  390. * @return \core\basic\Model
  391. */
  392. final public function exists($subSql)
  393. {
  394. if (is_callable($subSql)) { // 闭包子查询
  395. $subSql = $subSql(new self());
  396. }
  397. if (isset($this->sql['where']) && $this->sql['where']) {
  398. $this->sql['where'] .= " AND EXISTS ($subSql)";
  399. } else {
  400. $this->sql['where'] = "WHERE EXISTS ($subSql)";
  401. }
  402. return $this;
  403. }
  404. /**
  405. * 连贯操作:设置NOT EXISTS查询
  406. *
  407. * @param string $subSql
  408. * 传递子查询
  409. * @return \core\basic\Model
  410. */
  411. final public function notExists($subSql)
  412. {
  413. if (is_callable($subSql)) { // 闭包子查询
  414. $subSql = $subSql(new self());
  415. }
  416. if (isset($this->sql['where']) && $this->sql['where']) {
  417. $this->sql['where'] .= " AND NOT EXISTS ($subSql)";
  418. } else {
  419. $this->sql['where'] = "WHERE NOT EXISTS ($subSql)";
  420. }
  421. return $this;
  422. }
  423. /**
  424. * 连贯操作:设置IN查询
  425. *
  426. * @param string $field
  427. * 传递需要比对的字段,如: 'username'
  428. * @param mixed $range
  429. * 字符串、数组、子查询,如:'1,2,3',array(1,2,3);
  430. * @return \core\basic\Model
  431. */
  432. final public function in($field, $range)
  433. {
  434. if (! $field)
  435. return $this;
  436. if (is_array($range)) {
  437. if (count($range) == 1) { // 单只有一个值时使用直接使用等于,提高读取性能
  438. $in_string = "$field='$range[0]'";
  439. } else {
  440. $in_string = "$field IN (" . implode_quot(',', $range) . ")";
  441. }
  442. } else {
  443. if (preg_match('/,/', $range)) {
  444. $in_string = "$field IN (" . implode_quot(',', explode(',', $range)) . ")";
  445. } else { // 传递单个字符串时直接相等处理
  446. $in_string = "$field = '$range'";
  447. }
  448. }
  449. if (isset($this->sql['where']) && $this->sql['where']) {
  450. $this->sql['where'] .= " AND $in_string";
  451. } else {
  452. $this->sql['where'] = "WHERE $in_string";
  453. }
  454. return $this;
  455. }
  456. /**
  457. * 连贯操作:设置NOT IN查询
  458. *
  459. * @param string $field
  460. * 传递需要比对的字段,如: id NOT IN (1,2,3)
  461. * @param mixed $range
  462. * 字符串、数组、子查询
  463. * @return \core\basic\Model
  464. */
  465. final public function notIn($field, $range)
  466. {
  467. if (! $field)
  468. return $this;
  469. if (is_array($range)) {
  470. $in_string = implode_quot(',', $range);
  471. } else {
  472. if (preg_match('/,/', $range)) {
  473. $in_string = implode_quot(',', explode(',', $range));
  474. } else {
  475. $in_string = "'$range'";
  476. }
  477. }
  478. if (isset($this->sql['where']) && $this->sql['where']) {
  479. $this->sql['where'] .= " AND $field NOT IN ($in_string)";
  480. } else {
  481. $this->sql['where'] = "WHERE $field NOT IN ($in_string)";
  482. }
  483. return $this;
  484. }
  485. /**
  486. * 连贯操作:设置关键字条件匹配
  487. *
  488. * @param string $field
  489. * 字段名,支持数组传递多个字段或多个字段用逗号隔开
  490. * @param string $keyword
  491. * 匹配关键字
  492. * @param string $matchType
  493. * 匹配模式,默认为all,可选left,right,equal
  494. * @return \core\database\Operate
  495. */
  496. final public function like($field, $keyword, $matchType = "all")
  497. {
  498. if (! $field)
  499. return $this;
  500. switch ($matchType) {
  501. case 'left':
  502. $keyword = "$keyword%";
  503. break;
  504. case 'right':
  505. $keyword = "%$keyword";
  506. break;
  507. case 'equal':
  508. case '==':
  509. $keyword = "$keyword";
  510. break;
  511. default:
  512. $keyword = "%$keyword%";
  513. }
  514. if (is_array($field) || preg_match('/,/', $field)) {
  515. if (! is_array($field)) {
  516. $field = explode(',', $field);
  517. }
  518. foreach ($field as $value) {
  519. if (isset($sqlStr)) {
  520. $sqlStr .= " OR $value LIKE '$keyword'";
  521. } else {
  522. $sqlStr = "$value LIKE '$keyword'";
  523. }
  524. }
  525. } else {
  526. $sqlStr = "$field LIKE '$keyword'";
  527. }
  528. if (isset($this->sql['where']) && $this->sql['where']) {
  529. $this->sql['where'] .= " AND ($sqlStr)";
  530. } else {
  531. $this->sql['where'] = "WHERE ($sqlStr)";
  532. }
  533. return $this;
  534. }
  535. /**
  536. * 连贯操作:设置关键字条件不匹配
  537. *
  538. * @param string $field
  539. * 字段名
  540. * @param string $keyword
  541. * 匹配关键字
  542. * @param string $matchType
  543. * 匹配模式,默认为all,可选left,right
  544. * @return \core\database\Operate
  545. */
  546. final public function notLike($field, $keyword, $matchType = "all")
  547. {
  548. if (! $field)
  549. return $this;
  550. switch ($matchType) {
  551. case 'left':
  552. $keyword = "$keyword%";
  553. break;
  554. case 'right':
  555. $keyword = "%$keyword";
  556. break;
  557. case 'equal':
  558. case '==':
  559. $keyword = "$keyword";
  560. break;
  561. default:
  562. $keyword = "%$keyword%";
  563. }
  564. if (is_array($field) || preg_match('/,/', $field)) {
  565. if (! is_array($field)) {
  566. $field = explode(',', $field);
  567. }
  568. foreach ($field as $value) {
  569. if (isset($sqlStr)) {
  570. $sqlStr .= " AND $value NOT LIKE '$keyword'";
  571. } else {
  572. $sqlStr = "$value NOT LIKE '$keyword'";
  573. }
  574. }
  575. } else {
  576. $sqlStr = "$field NOT LIKE '$keyword'";
  577. }
  578. if (isset($this->sql['where']) && $this->sql['where']) {
  579. $this->sql['where'] .= " AND ($sqlStr)";
  580. } else {
  581. $this->sql['where'] = "WHERE ($sqlStr)";
  582. }
  583. return $this;
  584. }
  585. /**
  586. * 连贯操作:设置查询排序
  587. *
  588. * @param mixed $order
  589. * 可以为字符串、数组,
  590. * 字符串模式:如"id DESC,name",
  591. * 数组模式:array('id'=>'DESC','name')
  592. * @return \core\basic\Model
  593. */
  594. final public function order($order)
  595. {
  596. if (is_array($order)) {
  597. $order_string = 'ORDER BY ';
  598. foreach ($order as $key => $value) {
  599. if (is_int($key)) {
  600. $order_string .= $value . ',';
  601. } else {
  602. $order_string .= $key . ' ' . $value . ',';
  603. }
  604. }
  605. $this->sql['order'] = substr($order_string, 0, - 1);
  606. } else {
  607. $this->sql['order'] = 'ORDER BY ' . $order;
  608. }
  609. return $this;
  610. }
  611. /**
  612. * 连贯操作:设置查询数量
  613. *
  614. * @param string $limit
  615. * 设置限制语句,可接受:
  616. * 单个参数数,如 1,条数
  617. * 单个参数字符串,如"1,10"
  618. * 两个参数数字,如:1,10
  619. * 注意:当使用了分页时会无效
  620. * @return \core\basic\Model
  621. */
  622. final public function limit($limit)
  623. {
  624. $var_num = func_num_args();
  625. if ($var_num > 1 || preg_match('/,/', $limit)) {
  626. if ($var_num > 1) {
  627. $var_arr = func_get_args();
  628. } else {
  629. $var_arr = explode(',', $limit);
  630. }
  631. switch (get_db_type()) {
  632. case 'mysql':
  633. $this->sql['limit'] = 'LIMIT ' . $var_arr[0] . ',' . $var_arr[1];
  634. break;
  635. case 'sqlite':
  636. $this->sql['limit'] = 'LIMIT ' . $var_arr[1] . ' OFFSET ' . $var_arr[0];
  637. break;
  638. case 'pgsql':
  639. $this->sql['limit'] = 'LIMIT ' . $var_arr[1] . ' OFFSET ' . $var_arr[0];
  640. break;
  641. }
  642. } else {
  643. $this->sql['limit'] = 'LIMIT ' . $limit;
  644. }
  645. return $this;
  646. }
  647. /**
  648. * 连贯操作:设置分组查询
  649. *
  650. * @param mixed $group
  651. * 可以传递字符串、数字数组,如"name,sex",array('name','sex')
  652. * @return \core\basic\Model
  653. */
  654. final public function group($group)
  655. {
  656. if (is_array($group)) {
  657. $group_string = 'GROUP BY ';
  658. foreach ($group as $key => $value) {
  659. $group_string .= $value . ',';
  660. }
  661. $this->sql['group'] = substr($group_string, 0, - 1);
  662. } else {
  663. $this->sql['group'] = 'GROUP BY ' . $group;
  664. }
  665. return $this;
  666. }
  667. /**
  668. * 连贯操作:设置查询条件having
  669. * 在 SQL 中增加 HAVING 子句原因是,WHERE 关键字无法与合计函数一起使用。
  670. *
  671. * @param string $having
  672. * 传入字符串,需要完整having语句
  673. * @return \core\basic\Model
  674. */
  675. final public function having($having, $inConnect = 'AND', $outConnect = 'AND')
  676. {
  677. if (isset($this->sql['having']) && $this->sql['having']) {
  678. $this->sql['having'] .= ' ' . $outConnect . '(';
  679. } else {
  680. $this->sql['having'] = 'HAVING(';
  681. }
  682. if (is_array($having)) {
  683. $having_string = '';
  684. $flag = false;
  685. foreach ($having as $key => $value) {
  686. if ($flag) { // 条件之间内部AND连接
  687. $having_string .= ' ' . $inConnect . ' ';
  688. } else {
  689. $flag = true;
  690. }
  691. if (! is_int($key)) {
  692. $having_string .= $key . "='" . $value . "' ";
  693. } else {
  694. $having_string .= $value;
  695. }
  696. }
  697. $this->sql['having'] .= $having_string . ')';
  698. } else {
  699. $this->sql['having'] .= $having . ')';
  700. }
  701. return $this;
  702. }
  703. /**
  704. * 连贯操作:设置连接查询
  705. *
  706. * @param array $join
  707. * 可以为一维或二维数组,array('table','a.id=b.id','LEFT'),
  708. * array第一个参数为数据表,第二个参数为ON条件,第三个参数为类型,
  709. * 二维模式:array(
  710. * array('table b','a.id=b.aid','LEFT'),
  711. * array('table c','a.id=c.aid','LEFT')
  712. * )
  713. * @return \core\basic\Model
  714. */
  715. final public function join(array $join)
  716. {
  717. if (count($join) == count($join, 1)) {
  718. $join_string = '';
  719. if (isset($join[2])) {
  720. $join_string .= ' ' . $join[2] . ' JOIN ';
  721. } else {
  722. $join_string .= ' LEFT JOIN ';
  723. }
  724. $join_string .= $join[0] . ' ON ' . $join[1];
  725. if (isset($this->sql['join'])) {
  726. $this->sql['join'] .= $join_string;
  727. } else {
  728. $this->sql['join'] = $join_string;
  729. }
  730. } else {
  731. foreach ($join as $key => $value) {
  732. $this->join($value);
  733. }
  734. }
  735. return $this;
  736. }
  737. /**
  738. * 连贯操作:合并两个或多个 SELECT 语句的结果集
  739. *
  740. * @param array $subSql
  741. * 子查询可以使用数字数组传递多个
  742. * @param string $isAll
  743. * 是否UNION ALL
  744. * @return \core\basic\Model
  745. */
  746. final public function union($subSql, $isAll = false)
  747. {
  748. if (! isset($this->sql['union'])) {
  749. $this->sql['union'] = '';
  750. }
  751. if (is_callable($subSql)) { // 闭包子查询
  752. $subSql = $subSql(new self());
  753. }
  754. if (is_array($subSql)) {
  755. foreach ($subSql as $key => $value) {
  756. $this->union($value, $isAll);
  757. }
  758. } else {
  759. if ($isAll) {
  760. $this->sql['union'] .= " UNION ALL($subSql)";
  761. } else {
  762. $this->sql['union'] .= " UNION ($subSql)";
  763. }
  764. }
  765. return $this;
  766. }
  767. /**
  768. * 连贯操作:数据分页
  769. * 传递一个参数时为页数,传递两个参数时第二个为分页大小
  770. *
  771. * @return \core\basic\Model
  772. */
  773. final public function page($args = 1)
  774. {
  775. if ($args === false) {
  776. $this->sql['paging'] = false;
  777. return $this;
  778. }
  779. $this->sql['paging'] = true;
  780. $paging = Paging::getInstance();
  781. $var_num = func_num_args();
  782. if ($var_num > 1 || preg_match('/,/', $args)) {
  783. if ($var_num > 1) {
  784. $var_arr = func_get_args();
  785. } else {
  786. $var_arr = explode(',', $args);
  787. }
  788. $paging->page = $var_arr[0];
  789. $paging->pageSize = $var_arr[1];
  790. if (isset($var_arr[2])) {
  791. $paging->start = $var_arr[2];
  792. }
  793. } else {
  794. $paging->page = $args;
  795. }
  796. return $this;
  797. }
  798. /**
  799. * 连贯操作:待插入或更新数据数组,分解insert、update函数,实现 table($table)->data($data)->insert();
  800. *
  801. * @param array $data
  802. * @return \core\basic\Model
  803. */
  804. final public function data($data)
  805. {
  806. $this->sql['data'] = $data;
  807. return $this;
  808. }
  809. /**
  810. * 连贯操作:生成关联插入数据,如 用户对应多个角色,relation($ucode,$rcodes)
  811. *
  812. * @param string $field
  813. * 第一个字段的值,如用户编码
  814. * @param array $array
  815. * 第二个字段的值数组,如用户所属多个角色数组
  816. * @return \core\basic\Model
  817. */
  818. final public function relation($field, array $array)
  819. {
  820. if ($array) {
  821. foreach ($array as $value) {
  822. $data[] = array(
  823. $field,
  824. $value
  825. );
  826. }
  827. $this->sql['data'] = $data;
  828. }
  829. return $this;
  830. }
  831. /**
  832. * 连贯操作:用于从一个表复制信息到另一个表 ,实现INSERT INTO SELECT的功能
  833. *
  834. * @param string $subSql
  835. */
  836. final public function from($subSql)
  837. {
  838. if (is_callable($subSql)) { // 闭包子查询
  839. $subSql = $subSql(new self());
  840. }
  841. $this->sql['from'] = $subSql;
  842. return $this;
  843. }
  844. // ********************************数据查询************************************************************
  845. /**
  846. * 多条数据查询模型,select方法查询结果不存在,返回空数组
  847. *
  848. * @param string $type
  849. * 可选传递1,2,3返回不同格式数据数组
  850. * @return array
  851. */
  852. final public function select($type = null)
  853. {
  854. // 闭包查询
  855. if (is_callable($type)) {
  856. $type($this);
  857. return $this->select();
  858. }
  859. if (! isset($this->sql['field']) || ! $this->sql['field'])
  860. $this->sql['field'] = '*';
  861. // 如果调用了分页函数且分页,则执行分页处理
  862. if (isset($this->sql['paging']) && $this->sql['paging']) {
  863. if ($this->sql['group'] || $this->sql['distinct']) { // 解决使用分组时count(*)分页不准问题
  864. if (get_db_type() == 'mysql') {
  865. $this->limit(Paging::getInstance()->quikLimit()); // 分页
  866. $this->sql['field'] = 'SQL_CALC_FOUND_ROWS ' . $this->sql['field']; // 添加查询总记录
  867. $sql = $this->buildSql($this->selectSql);
  868. $result = $this->getDb()->all($sql, $type);
  869. $count_sql = "select FOUND_ROWS() as sum";
  870. if (! ! $rs = $this->getDb()->one($count_sql)) {
  871. $total = $rs->sum;
  872. // 分页内容
  873. $limit = Paging::getInstance()->limit($total, true); // 生成分页代码
  874. }
  875. } else {
  876. $count_sql = $this->buildSql($this->countSql2, false);
  877. // 获取记录总数
  878. if (! ! $rs = $this->getDb()->all($count_sql)) {
  879. $total = count($rs);
  880. // 分页内容
  881. $limit = Paging::getInstance()->limit($total, true);
  882. // 获取分页参数并设置分页
  883. $this->limit($limit);
  884. }
  885. }
  886. } else {
  887. // 生成总数计算语句
  888. $count_sql = $this->buildSql($this->countSql, false);
  889. // 获取记录总数
  890. if (! ! $rs = $this->getDb()->one($count_sql)) {
  891. $total = $rs->sum;
  892. // 分页内容
  893. $limit = Paging::getInstance()->limit($total, true);
  894. // 获取分页参数并设置分页
  895. $this->limit($limit);
  896. }
  897. }
  898. }
  899. // 构建查询语句
  900. if ($type === false) {
  901. return $this->buildSql($this->selectSql,false);
  902. } else {
  903. $sql = $this->buildSql($this->selectSql);
  904. }
  905. if (! isset($result)) {
  906. $result = $this->getDb()->all($sql, $type);
  907. }
  908. return $this->outData($result);
  909. }
  910. /**
  911. * 单条数据查询模型,find 方法查询结果不存在,返回 null
  912. *
  913. * @param string $type
  914. * 可选传递1,2,3返回不同格式数据数组
  915. * @return string|boolean|string
  916. */
  917. final public function find($type = null)
  918. {
  919. // 闭包查询
  920. if (is_callable($type)) {
  921. $type($this);
  922. return $this->find();
  923. }
  924. if (! isset($this->sql['field']))
  925. $this->sql['field'] = '*';
  926. $this->limit(1); // 强制查询一条
  927. $sql = $this->buildSql($this->selectSql); // 构建语句
  928. if ($type === false) {
  929. return $sql;
  930. }
  931. $result = $this->getDb()->one($sql, $type);
  932. return $this->outData($result);
  933. }
  934. /**
  935. * 返回指定字段数据数组
  936. *
  937. * @param string $name
  938. * 字段名字符串或数字数组,单个字段,返回一维数组,如果多个字段,返回二维数组数
  939. * @param string $key
  940. * 指定返回数组的键值字段
  941. * @return array
  942. */
  943. final public function column($fields, $key = null)
  944. {
  945. // 配置传递的字段
  946. if (is_array($fields)) {
  947. $fields = implode(',', $fields);
  948. }
  949. // 如果传递字段不含指定键则添加
  950. if ($key && ! preg_match('/(.*,|^)(' . $key . ')(,.*|$)/', $fields)) {
  951. $this->sql['field'] = $key . ',' . $fields;
  952. } else {
  953. $this->sql['field'] = $fields;
  954. }
  955. $sql = $this->buildSql($this->selectSql);
  956. $result = $this->getDb()->all($sql, 1);
  957. $data = array();
  958. foreach ($result as $vkey => $value) {
  959. if ($key) {
  960. $key_value = $value[$key];
  961. if (is_array($value) && count($value) == 2) {
  962. unset($value[$key]);
  963. $data[$key_value] = current($value);
  964. } else {
  965. $data[$key_value] = $value;
  966. }
  967. } else {
  968. if (is_array($value) && count($value) == 1) {
  969. $data[] = current($value);
  970. } else {
  971. $data[] = $value;
  972. }
  973. }
  974. }
  975. return $this->outData($data);
  976. }
  977. /**
  978. * 返回指定字段的一条数据的值模式
  979. *
  980. * @param string $name
  981. * 字段名
  982. * @return string 返回字段值
  983. */
  984. final public function value($field)
  985. {
  986. $this->sql['field'] = $field;
  987. $this->limit(1);
  988. $sql = $this->buildSql($this->selectSql);
  989. $result = $this->getDb()->one($sql, 2);
  990. if (isset($result[0])) {
  991. return $this->outData($result[0]);
  992. } else {
  993. return null;
  994. }
  995. }
  996. /**
  997. * 返回指定列最大值
  998. *
  999. * @param string $name
  1000. * 字段名
  1001. * @return boolean
  1002. */
  1003. final public function max($field)
  1004. {
  1005. $this->sql['field'] = "MAX(`$field`)";
  1006. $sql = $this->buildSql($this->selectSql);
  1007. $result = $this->getDb()->one($sql, 2);
  1008. return $this->outData($result[0]);
  1009. }
  1010. /**
  1011. * 返回指定列最小值
  1012. *
  1013. * @param string $name
  1014. * 字段名
  1015. * @return boolean
  1016. */
  1017. final public function min($field)
  1018. {
  1019. $this->sql['field'] = "MIN(`$field`)";
  1020. $sql = $this->buildSql($this->selectSql);
  1021. $result = $this->getDb()->one($sql, 2);
  1022. return $this->outData($result[0]);
  1023. }
  1024. /**
  1025. * 返回指定列平均值
  1026. *
  1027. * @param string $name
  1028. * 字段名
  1029. * @return boolean
  1030. */
  1031. final public function avg($field)
  1032. {
  1033. $this->sql['field'] = "AVG(`$field`)";
  1034. $sql = $this->buildSql($this->selectSql);
  1035. $result = $this->getDb()->one($sql, 2);
  1036. return $this->outData($result[0]);
  1037. }
  1038. /**
  1039. * 返回指定列合计值
  1040. *
  1041. * @param string $name
  1042. * 字段名
  1043. * @return boolean
  1044. */
  1045. final public function sum($field)
  1046. {
  1047. $this->sql['field'] = "SUM(`$field`)";
  1048. $sql = $this->buildSql($this->selectSql);
  1049. $result = $this->getDb()->one($sql, 2);
  1050. if ($result[0]) {
  1051. return $this->outData($result[0]);
  1052. } else {
  1053. return 0;
  1054. }
  1055. }
  1056. // 返回统计数据
  1057. final public function count()
  1058. {
  1059. $this->sql['field'] = "COUNT(*)";
  1060. $sql = $this->buildSql($this->selectSql);
  1061. $result = $this->getDb()->one($sql, 2);
  1062. if ($result[0]) {
  1063. return $this->outData($result[0]);
  1064. } else {
  1065. return 0;
  1066. }
  1067. }
  1068. // ******************************数据插入*******************************************************
  1069. /**
  1070. * 数据插入模型
  1071. *
  1072. * @param array $data
  1073. * 可以为一维或二维数组,
  1074. * 一维数组:array('username'=>"xsh",'sex'=>'男'),
  1075. * 二维数组:array(
  1076. * array('username'=>"xsh",'sex'=>'男'),
  1077. * array('username'=>"gmx",'sex'=>'女')
  1078. * )
  1079. * @param boolean $batch
  1080. * 是否启用批量一次插入功能,默认true
  1081. * @return boolean|boolean|array
  1082. */
  1083. final public function insert(array $data = array(), $batch = true)
  1084. {
  1085. // 未传递数据时,使用data函数插入数据
  1086. if (! $data && isset($this->sql['data'])) {
  1087. return $this->insert($this->sql['data']);
  1088. }
  1089. if (is_array($data)) {
  1090. if (! $data)
  1091. return;
  1092. if (count($data) == count($data, 1)) { // 单条数据
  1093. $keys = '';
  1094. $values = '';
  1095. foreach ($data as $key => $value) {
  1096. $this->checkKey($key);
  1097. if (! is_numeric($key)) {
  1098. $keys .= "`" . $key . "`,";
  1099. $values .= "'" . $value . "',";
  1100. }
  1101. }
  1102. if ($this->autoTimestamp || (isset($this->sql['auto_time']) && $this->sql['auto_time'] == true)) {
  1103. $keys .= "`" . $this->createTimeField . "`,`" . $this->updateTimeField . "`,";
  1104. if ($this->intTimeFormat) {
  1105. $values .= "'" . time() . "','" . time() . "',";
  1106. } else {
  1107. $values .= "'" . date('Y-m-d H:i:s') . "','" . date('Y-m-d H:i:s') . "',";
  1108. }
  1109. }
  1110. if ($keys) { // 如果插入数据关联字段,则字段以关联数据为准,否则以设置字段为准
  1111. $this->sql['field'] = '(' . substr($keys, 0, - 1) . ')';
  1112. } elseif (isset($this->sql['field']) && $this->sql['field']) {
  1113. $this->sql['field'] = "({$this->sql['field']})";
  1114. }
  1115. $this->sql['value'] = "(" . substr($values, 0, - 1) . ")";
  1116. $sql = $this->buildSql($this->insertSql);
  1117. } else { // 多条数据
  1118. if ($batch) { // 批量一次性插入
  1119. $key_string = '';
  1120. $value_string = '';
  1121. $flag = false;
  1122. foreach ($data as $keys => $value) {
  1123. if (! $flag) {
  1124. $value_string .= ' SELECT ';
  1125. } else {
  1126. $value_string .= ' UNION All SELECT ';
  1127. }
  1128. foreach ($value as $key2 => $value2) {
  1129. // 字段获取只执行一次
  1130. if (! $flag && ! is_numeric($key2)) {
  1131. $this->checkKey($key2);
  1132. $key_string .= "`" . $key2 . "`,";
  1133. }
  1134. $value_string .= "'" . $value2 . "',";
  1135. }
  1136. $flag = true;
  1137. if ($this->autoTimestamp || (isset($this->sql['auto_time']) && $this->sql['auto_time'] == true)) {
  1138. if ($this->intTimeFormat) {
  1139. $value_string .= "'" . time() . "','" . time() . "',";
  1140. } else {
  1141. $value_string .= "'" . date('Y-m-d H:i:s') . "','" . date('Y-m-d H:i:s') . "',";
  1142. }
  1143. }
  1144. $value_string = substr($value_string, 0, - 1);
  1145. }
  1146. if ($this->autoTimestamp || (isset($this->sql['auto_time']) && $this->sql['auto_time'] == true)) {
  1147. $key_string .= "`" . $this->createTimeField . "`,`" . $this->updateTimeField . "`,";
  1148. }
  1149. if ($key_string) { // 如果插入数据关联字段,则字段以关联数据为准,否则以设置字段为准
  1150. $this->sql['field'] = '(' . substr($key_string, 0, - 1) . ')';
  1151. } elseif (isset($this->sql['field']) && $this->sql['field']) {
  1152. $this->sql['field'] = "({$this->sql['field']})";
  1153. }
  1154. $this->sql['value'] = $value_string;
  1155. $sql = $this->buildSql($this->insertMultSql);
  1156. // 判断SQL语句是否超过数据库设置
  1157. if (get_db_type() == 'mysql') {
  1158. $max_allowed_packet = $this->getDb()->one('SELECT @@global.max_allowed_packet', 2);
  1159. } else {
  1160. $max_allowed_packet = 1 * 1024 * 1024; // 其他类型数据库按照1M限制
  1161. }
  1162. if (strlen($sql) > $max_allowed_packet) { // 如果要插入的数据过大,则转换为一条条插入
  1163. return $this->insert($data, false);
  1164. }
  1165. } else { // 批量一条条插入
  1166. foreach ($data as $keys => $value) {
  1167. $result = $this->insert($value);
  1168. }
  1169. return $result;
  1170. }
  1171. }
  1172. } elseif ($this->sql['from']) {
  1173. if (isset($this->sql['field']) && $this->sql['field']) { // 表指定字段复制
  1174. $this->sql['field'] = "({$this->sql['field']})";
  1175. }
  1176. $sql = $this->buildSql($this->insertFromSql);
  1177. } else {
  1178. return;
  1179. }
  1180. $sql = preg_replace_r('/pboot:if/i', 'pboot@if', $sql); // 过滤插入cms条件语句
  1181. $sql = preg_replace_r('/pboot:sql/i', 'pboot@sql', $sql); // 过滤插入cms条件语句
  1182. return $this->getDb()->amd($sql);
  1183. }
  1184. /**
  1185. * 插入数据并返回自增ID值
  1186. *
  1187. * @param array $data
  1188. * 可以为一维或二维数组
  1189. * @param boolean $batch
  1190. * 是否启用批量一次插入功能,默认true
  1191. * @return number|string|boolean
  1192. */
  1193. final public function insertGetId(array $data = null, $batch = true)
  1194. {
  1195. if ($this->insert($data, $batch)) {
  1196. return $this->getDb()->insertId();
  1197. } else {
  1198. return false;
  1199. }
  1200. }
  1201. // ******************************数据更新*******************************************************
  1202. /**
  1203. * 数据更新
  1204. *
  1205. * @param array $data
  1206. * 传入字符串、数组
  1207. * 字符串如:"username='xsh'"
  1208. * 数组如:array('username'=>'test','sex'=>'女')
  1209. * @return void|boolean|boolean|array
  1210. */
  1211. final public function update($data = null)
  1212. {
  1213. // 未传递数据时使用data函数插入数据
  1214. if (! $data && $this->sql['data']) {
  1215. return $this->update($this->sql['data']);
  1216. }
  1217. $update_string = '';
  1218. if (is_array($data)) {
  1219. if (! $data)
  1220. return;
  1221. foreach ($data as $key => $value) {
  1222. $this->checkKey($key);
  1223. $temp_v_start = substr($value, 0, 2);
  1224. $temp_v_end = substr($value, 2);
  1225. if (is_numeric($temp_v_end) && $temp_v_start == "-=") {
  1226. $update_string .= "`$key`= $key-$temp_v_end,"; // 自减
  1227. } elseif (is_numeric($temp_v_end) && $temp_v_start == "+=") {
  1228. $update_string .= "`$key`= $key+$temp_v_end,"; // 自加
  1229. } else {
  1230. $update_string .= "`$key`='$value',";
  1231. }
  1232. }
  1233. $update_string = substr($update_string, 0, - 1);
  1234. } else {
  1235. $update_string = $data;
  1236. }
  1237. if ($this->autoTimestamp || (isset($this->sql['auto_time']) && $this->sql['auto_time'] == true)) {
  1238. if ($this->intTimeFormat) {
  1239. $update_string .= ",`" . $this->updateTimeField . "`=' " . time() . "'";
  1240. } else {
  1241. $update_string .= ",`" . $this->updateTimeField . "`=' " . date('Y-m-d H:i:s') . "'";
  1242. }
  1243. }
  1244. $this->sql['value'] = $update_string;
  1245. $sql = $this->buildSql($this->updateSql);
  1246. $sql = preg_replace_r('/pboot:if/i', 'pboot@if', $sql); // 过滤插入cms条件语句
  1247. $sql = preg_replace_r('/pboot:sql/i', 'pboot@sql', $sql); // 过滤插入cms条件语句
  1248. return $this->getDb()->amd($sql);
  1249. }
  1250. /**
  1251. * 更新指定字段
  1252. *
  1253. * @param string $field
  1254. * 字段名
  1255. * @param string $value
  1256. * 值
  1257. * @return boolean|boolean|array
  1258. */
  1259. final public function setField($field, $value)
  1260. {
  1261. $this->checkKey($field);
  1262. $this->sql['value'] = "`$field`='$value'";
  1263. if ($this->autoTimestamp || (isset($this->sql['auto_time']) && $this->sql['auto_time'] == true)) {
  1264. if ($this->intTimeFormat) {
  1265. $this->sql['value'] .= ",`" . $this->updateTimeField . "`=' " . time() . "'";
  1266. } else {
  1267. $this->sql['value'] .= ",`" . $this->updateTimeField . "`=' " . date('Y-m-d H:i:s') . "'";
  1268. }
  1269. }
  1270. $sql = $this->buildSql($this->updateSql);
  1271. return $this->getDb()->amd($sql);
  1272. }
  1273. /**
  1274. * 字段自增
  1275. *
  1276. * @param string $field
  1277. * 字段
  1278. * @param number $value
  1279. * 值
  1280. * @return boolean|boolean|array
  1281. */
  1282. final public function setInc($field, $value = 1)
  1283. {
  1284. $this->checkKey($field);
  1285. $this->sql['value'] = " `$field`= $field+$value";
  1286. if ($this->autoTimestamp || (isset($this->sql['auto_time']) && $this->sql['auto_time'] == true)) {
  1287. if ($this->intTimeFormat) {
  1288. $this->sql['value'] .= ",`" . $this->updateTimeField . "`=' " . time() . "'";
  1289. } else {
  1290. $this->sql['value'] .= ",`" . $this->updateTimeField . "`=' " . date('Y-m-d H:i:s') . "'";
  1291. }
  1292. }
  1293. $sql = $this->buildSql($this->updateSql);
  1294. return $this->getDb()->amd($sql);
  1295. }
  1296. /**
  1297. * 字段自减
  1298. *
  1299. * @param string $field
  1300. * 字段
  1301. * @param number $value
  1302. * 值
  1303. * @return boolean|boolean|array
  1304. */
  1305. final public function setDec($field, $value = 1)
  1306. {
  1307. $this->checkKey($field);
  1308. $this->sql['value'] = " `$field`= $field-$value";
  1309. if ($this->autoTimestamp || (isset($this->sql['auto_time']) && $this->sql['auto_time'] == true)) {
  1310. if ($this->intTimeFormat) {
  1311. $this->sql['value'] .= ",`" . $this->updateTimeField . "`=' " . time() . "'";
  1312. } else {
  1313. $this->sql['value'] .= ",`" . $this->updateTimeField . "`=' " . date('Y-m-d H:i:s') . "'";
  1314. }
  1315. }
  1316. $sql = $this->buildSql($this->updateSql);
  1317. return $this->getDb()->amd($sql);
  1318. }
  1319. // ***************************数据删除*******************************************************
  1320. /**
  1321. * 数据删除
  1322. *
  1323. * @param mixed $data
  1324. * 可以为字符串或数组,如"1,2,3",array(1,2,3)
  1325. * @param string $key
  1326. * 字段名,默认为id
  1327. * @return boolean|boolean|array
  1328. */
  1329. final public function delete($data = null, $key = null)
  1330. {
  1331. if ($data) {
  1332. if (! $key)
  1333. $key = $this->pk;
  1334. $this->checkKey($key);
  1335. if (is_array($data) || preg_match('/,/', $data)) {
  1336. $this->in($key, $data);
  1337. } else {
  1338. $this->where("$key='$data'");
  1339. }
  1340. }
  1341. $sql = $this->buildSql($this->deleteSql);
  1342. return $this->getDb()->amd($sql);
  1343. }
  1344. // 检测key值
  1345. private function checkKey($key)
  1346. {
  1347. if (! $key)
  1348. return;
  1349. if (! preg_match('/^[\w\.\-]+$/', $key)) {
  1350. error('传递的SQL数据中含有非法字符:' . $key);
  1351. }
  1352. }
  1353. //查询索引
  1354. public function checkIndexSql(): array
  1355. {
  1356. $sql = $this->buildSql($this->checkIndex);
  1357. $result = $this->getDb()->query($sql);
  1358. return $this->getDb()->fetchQuery($result);
  1359. }
  1360. }