Db.class.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: liu21st <liu21st@gmail.com>
  10. // +----------------------------------------------------------------------
  11. define('CLIENT_MULTI_RESULTS', 131072);
  12. /**
  13. * ThinkPHP 精简模式数据库中间层实现类 只支持Mysql
  14. */
  15. class Db {
  16. static private $_instance = null;
  17. // 是否自动释放查询结果
  18. protected $autoFree = false;
  19. // 是否显示调试信息 如果启用会在日志文件记录sql语句
  20. public $debug = false;
  21. // 是否使用永久连接
  22. protected $pconnect = false;
  23. // 当前SQL指令
  24. protected $queryStr = '';
  25. // 最后插入ID
  26. protected $lastInsID = null;
  27. // 返回或者影响记录数
  28. protected $numRows = 0;
  29. // 返回字段数
  30. protected $numCols = 0;
  31. // 事务指令数
  32. protected $transTimes = 0;
  33. // 错误信息
  34. protected $error = '';
  35. // 当前连接ID
  36. protected $linkID = null;
  37. // 当前查询ID
  38. protected $queryID = null;
  39. // 是否已经连接数据库
  40. protected $connected = false;
  41. // 数据库连接参数配置
  42. protected $config = '';
  43. // 数据库表达式
  44. protected $comparison = array('eq'=>'=','neq'=>'!=','gt'=>'>','egt'=>'>=','lt'=>'<','elt'=>'<=','notlike'=>'NOT LIKE','like'=>'LIKE');
  45. // 查询表达式
  46. protected $selectSql = 'SELECT%DISTINCT% %FIELDS% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%%LIMIT%';
  47. /**
  48. * 架构函数
  49. * @access public
  50. * @param array $config 数据库配置数组
  51. */
  52. public function __construct($config=''){
  53. if ( !extension_loaded('mysql') ) {
  54. throw_exception(L('_NOT_SUPPERT_').':mysql');
  55. }
  56. $this->config = $this->parseConfig($config);
  57. if(APP_DEBUG) {
  58. $this->debug = true;
  59. }
  60. }
  61. /**
  62. * 连接数据库方法
  63. * @access public
  64. * @throws ThinkExecption
  65. */
  66. public function connect() {
  67. if(!$this->connected) {
  68. $config = $this->config;
  69. // 处理不带端口号的socket连接情况
  70. $host = $config['hostname'].($config['hostport']?":{$config['hostport']}":'');
  71. $pconnect = !empty($config['params']['persist'])? $config['params']['persist']:$this->pconnect;
  72. if($pconnect) {
  73. $this->linkID = mysql_pconnect( $host, $config['username'], $config['password'],CLIENT_MULTI_RESULTS);
  74. }else{
  75. $this->linkID = mysql_connect( $host, $config['username'], $config['password'],true,CLIENT_MULTI_RESULTS);
  76. }
  77. if ( !$this->linkID || (!empty($config['database']) && !mysql_select_db($config['database'], $this->linkID)) ) {
  78. throw_exception(mysql_error());
  79. }
  80. $dbVersion = mysql_get_server_info($this->linkID);
  81. if ($dbVersion >= "4.1") {
  82. //使用UTF8存取数据库 需要mysql 4.1.0以上支持
  83. mysql_query("SET NAMES '".C('DB_CHARSET')."'", $this->linkID);
  84. }
  85. //设置 sql_model
  86. if($dbVersion >'5.0.1'){
  87. mysql_query("SET sql_mode=''",$this->linkID);
  88. }
  89. // 标记连接成功
  90. $this->connected = true;
  91. // 注销数据库连接配置信息
  92. unset($this->config);
  93. }
  94. }
  95. /**
  96. * 释放查询结果
  97. * @access public
  98. */
  99. public function free() {
  100. mysql_free_result($this->queryID);
  101. $this->queryID = 0;
  102. }
  103. /**
  104. * 执行查询 主要针对 SELECT, SHOW 等指令
  105. * 返回数据集
  106. * @access public
  107. * @param string $str sql指令
  108. * @return mixed
  109. * @throws ThinkExecption
  110. */
  111. public function query($str='') {
  112. $this->connect();
  113. if ( !$this->linkID ) return false;
  114. if ( $str != '' ) $this->queryStr = $str;
  115. //释放前次的查询结果
  116. if ( $this->queryID ) { $this->free(); }
  117. N('db_query',1);
  118. // 记录开始执行时间
  119. G('queryStartTime');
  120. $this->queryID = mysql_query($this->queryStr, $this->linkID);
  121. $this->debug();
  122. if ( !$this->queryID ) {
  123. if ( $this->debug )
  124. throw_exception($this->error());
  125. else
  126. return false;
  127. } else {
  128. $this->numRows = mysql_num_rows($this->queryID);
  129. return $this->getAll();
  130. }
  131. }
  132. /**
  133. * 执行语句 针对 INSERT, UPDATE 以及DELETE
  134. * @access public
  135. * @param string $str sql指令
  136. * @return integer
  137. * @throws ThinkExecption
  138. */
  139. public function execute($str='') {
  140. $this->connect();
  141. if ( !$this->linkID ) return false;
  142. if ( $str != '' ) $this->queryStr = $str;
  143. //释放前次的查询结果
  144. if ( $this->queryID ) { $this->free(); }
  145. N('db_write',1);
  146. $result = mysql_query($this->queryStr, $this->linkID) ;
  147. $this->debug();
  148. if ( false === $result) {
  149. if ( $this->debug )
  150. throw_exception($this->error());
  151. else
  152. return false;
  153. } else {
  154. $this->numRows = mysql_affected_rows($this->linkID);
  155. $this->lastInsID = mysql_insert_id($this->linkID);
  156. return $this->numRows;
  157. }
  158. }
  159. /**
  160. * 启动事务
  161. * @access public
  162. * @return void
  163. * @throws ThinkExecption
  164. */
  165. public function startTrans() {
  166. $this->connect(true);
  167. if ( !$this->linkID ) return false;
  168. //数据rollback 支持
  169. if ($this->transTimes == 0) {
  170. mysql_query('START TRANSACTION', $this->linkID);
  171. }
  172. $this->transTimes++;
  173. return ;
  174. }
  175. /**
  176. * 用于非自动提交状态下面的查询提交
  177. * @access public
  178. * @return boolen
  179. * @throws ThinkExecption
  180. */
  181. public function commit() {
  182. if ($this->transTimes > 0) {
  183. $result = mysql_query('COMMIT', $this->linkID);
  184. $this->transTimes = 0;
  185. if(!$result){
  186. throw_exception($this->error());
  187. return false;
  188. }
  189. }
  190. return true;
  191. }
  192. /**
  193. * 事务回滚
  194. * @access public
  195. * @return boolen
  196. * @throws ThinkExecption
  197. */
  198. public function rollback() {
  199. if ($this->transTimes > 0) {
  200. $result = mysql_query('ROLLBACK', $this->linkID);
  201. $this->transTimes = 0;
  202. if(!$result){
  203. throw_exception($this->error());
  204. return false;
  205. }
  206. }
  207. return true;
  208. }
  209. /**
  210. * 获得所有的查询数据
  211. * @access public
  212. * @return array
  213. * @throws ThinkExecption
  214. */
  215. public function getAll() {
  216. if ( !$this->queryID ) {
  217. throw_exception($this->error());
  218. return false;
  219. }
  220. //返回数据集
  221. $result = array();
  222. if($this->numRows >0) {
  223. while($row = mysql_fetch_assoc($this->queryID)){
  224. $result[] = $row;
  225. }
  226. mysql_data_seek($this->queryID,0);
  227. }
  228. return $result;
  229. }
  230. /**
  231. * 取得数据表的字段信息
  232. * @access public
  233. */
  234. public function getFields($tableName) {
  235. $result = $this->query('SHOW COLUMNS FROM '.$tableName);
  236. $info = array();
  237. foreach ($result as $key => $val) {
  238. $info[$val['Field']] = array(
  239. 'name' => $val['Field'],
  240. 'type' => $val['Type'],
  241. 'notnull' => (bool) ($val['Null'] === ''), // not null is empty, null is yes
  242. 'default' => $val['Default'],
  243. 'primary' => (strtolower($val['Key']) == 'pri'),
  244. 'autoinc' => (strtolower($val['Extra']) == 'auto_increment'),
  245. );
  246. }
  247. return $info;
  248. }
  249. /**
  250. * 取得数据库的表信息
  251. * @access public
  252. */
  253. public function getTables($dbName='') {
  254. if(!empty($dbName)) {
  255. $sql = 'SHOW TABLES FROM '.$dbName;
  256. }else{
  257. $sql = 'SHOW TABLES ';
  258. }
  259. $result = $this->query($sql);
  260. $info = array();
  261. foreach ($result as $key => $val) {
  262. $info[$key] = current($val);
  263. }
  264. return $info;
  265. }
  266. /**
  267. * 关闭数据库
  268. * @access public
  269. * @throws ThinkExecption
  270. */
  271. public function close() {
  272. if (!empty($this->queryID))
  273. mysql_free_result($this->queryID);
  274. if ($this->linkID && !mysql_close($this->linkID)){
  275. throw_exception($this->error());
  276. }
  277. $this->linkID = 0;
  278. }
  279. /**
  280. * 数据库错误信息
  281. * 并显示当前的SQL语句
  282. * @access public
  283. * @return string
  284. */
  285. public function error() {
  286. $this->error = mysql_error($this->linkID);
  287. if($this->queryStr!=''){
  288. $this->error .= "\n [ SQL语句 ] : ".$this->queryStr;
  289. }
  290. return $this->error;
  291. }
  292. /**
  293. * SQL指令安全过滤
  294. * @access public
  295. * @param string $str SQL字符串
  296. * @return string
  297. */
  298. public function escapeString($str) {
  299. return mysql_escape_string($str);
  300. }
  301. /**
  302. * 析构方法
  303. * @access public
  304. */
  305. public function __destruct() {
  306. // 关闭连接
  307. $this->close();
  308. }
  309. /**
  310. * 取得数据库类实例
  311. * @static
  312. * @access public
  313. * @return mixed 返回数据库驱动类
  314. */
  315. public static function getInstance($db_config='') {
  316. if ( self::$_instance==null ){
  317. self::$_instance = new Db($db_config);
  318. }
  319. return self::$_instance;
  320. }
  321. /**
  322. * 分析数据库配置信息,支持数组和DSN
  323. * @access private
  324. * @param mixed $db_config 数据库配置信息
  325. * @return string
  326. */
  327. private function parseConfig($db_config='') {
  328. if ( !empty($db_config) && is_string($db_config)) {
  329. // 如果DSN字符串则进行解析
  330. $db_config = $this->parseDSN($db_config);
  331. }else if(empty($db_config)){
  332. // 如果配置为空,读取配置文件设置
  333. $db_config = array (
  334. 'dbms' => C('DB_TYPE'),
  335. 'username' => C('DB_USER'),
  336. 'password' => C('DB_PWD'),
  337. 'hostname' => C('DB_HOST'),
  338. 'hostport' => C('DB_PORT'),
  339. 'database' => C('DB_NAME'),
  340. 'dsn' => C('DB_DSN'),
  341. 'params' => C('DB_PARAMS'),
  342. );
  343. }
  344. return $db_config;
  345. }
  346. /**
  347. * DSN解析
  348. * 格式: mysql://username:passwd@localhost:3306/DbName
  349. * @static
  350. * @access public
  351. * @param string $dsnStr
  352. * @return array
  353. */
  354. public function parseDSN($dsnStr) {
  355. if( empty($dsnStr) ){return false;}
  356. $info = parse_url($dsnStr);
  357. if($info['scheme']){
  358. $dsn = array(
  359. 'dbms' => $info['scheme'],
  360. 'username' => isset($info['user']) ? $info['user'] : '',
  361. 'password' => isset($info['pass']) ? $info['pass'] : '',
  362. 'hostname' => isset($info['host']) ? $info['host'] : '',
  363. 'hostport' => isset($info['port']) ? $info['port'] : '',
  364. 'database' => isset($info['path']) ? substr($info['path'],1) : ''
  365. );
  366. }else {
  367. preg_match('/^(.*?)\:\/\/(.*?)\:(.*?)\@(.*?)\:([0-9]{1, 6})\/(.*?)$/',trim($dsnStr),$matches);
  368. $dsn = array (
  369. 'dbms' => $matches[1],
  370. 'username' => $matches[2],
  371. 'password' => $matches[3],
  372. 'hostname' => $matches[4],
  373. 'hostport' => $matches[5],
  374. 'database' => $matches[6]
  375. );
  376. }
  377. return $dsn;
  378. }
  379. /**
  380. * 数据库调试 记录当前SQL
  381. * @access protected
  382. */
  383. protected function debug() {
  384. // 记录操作结束时间
  385. if ( $this->debug ) {
  386. G('queryEndTime');
  387. Log::record($this->queryStr." [ RunTime:".G('queryStartTime','queryEndTime',6)."s ]",Log::SQL);
  388. }
  389. }
  390. /**
  391. * 设置锁机制
  392. * @access protected
  393. * @return string
  394. */
  395. protected function parseLock($lock=false) {
  396. if(!$lock) return '';
  397. if('ORACLE' == $this->dbType) {
  398. return ' FOR UPDATE NOWAIT ';
  399. }
  400. return ' FOR UPDATE ';
  401. }
  402. /**
  403. * set分析
  404. * @access protected
  405. * @param array $data
  406. * @return string
  407. */
  408. protected function parseSet($data) {
  409. foreach ($data as $key=>$val){
  410. $value = $this->parseValue($val);
  411. if(is_scalar($value)) // 过滤非标量数据
  412. $set[] = $this->parseKey($key).'='.$value;
  413. }
  414. return ' SET '.implode(',',$set);
  415. }
  416. /**
  417. * value分析
  418. * @access protected
  419. * @param mixed $value
  420. * @return string
  421. */
  422. protected function parseValue($value) {
  423. if(is_string($value)) {
  424. $value = '\''.$this->escapeString($value).'\'';
  425. }elseif(isset($value[0]) && is_string($value[0]) && strtolower($value[0]) == 'exp'){
  426. $value = $this->escapeString($value[1]);
  427. }elseif(is_null($value)){
  428. $value = 'null';
  429. }
  430. return $value;
  431. }
  432. /**
  433. * field分析
  434. * @access protected
  435. * @param mixed $fields
  436. * @return string
  437. */
  438. protected function parseField($fields) {
  439. if(is_array($fields)) {
  440. // 完善数组方式传字段名的支持
  441. // 支持 'field1'=>'field2' 这样的字段别名定义
  442. $array = array();
  443. foreach ($fields as $key=>$field){
  444. if(!is_numeric($key))
  445. $array[] = $this->parseKey($key).' AS '.$this->parseKey($field);
  446. else
  447. $array[] = $this->parseKey($field);
  448. }
  449. $fieldsStr = implode(',', $array);
  450. }elseif(is_string($fields) && !empty($fields)) {
  451. $fieldsStr = $this->parseKey($fields);
  452. }else{
  453. $fieldsStr = '*';
  454. }
  455. return $fieldsStr;
  456. }
  457. /**
  458. * table分析
  459. * @access protected
  460. * @param mixed $table
  461. * @return string
  462. */
  463. protected function parseTable($tables) {
  464. if(is_string($tables))
  465. $tables = explode(',',$tables);
  466. array_walk($tables, array(&$this, 'parseKey'));
  467. return implode(',',$tables);
  468. }
  469. /**
  470. * where分析
  471. * @access protected
  472. * @param mixed $where
  473. * @return string
  474. */
  475. protected function parseWhere($where) {
  476. $whereStr = '';
  477. if(is_string($where)) {
  478. // 直接使用字符串条件
  479. $whereStr = $where;
  480. }else{ // 使用数组条件表达式
  481. if(isset($where['_logic'])) {
  482. // 定义逻辑运算规则 例如 OR XOR AND NOT
  483. $operate = ' '.strtoupper($where['_logic']).' ';
  484. unset($where['_logic']);
  485. }else{
  486. // 默认进行 AND 运算
  487. $operate = ' AND ';
  488. }
  489. foreach ($where as $key=>$val){
  490. $whereStr .= "( ";
  491. if(0===strpos($key,'_')) {
  492. // 解析特殊条件表达式
  493. $whereStr .= $this->parseThinkWhere($key,$val);
  494. }else{
  495. $key = $this->parseKey($key);
  496. if(is_array($val)) {
  497. if(is_string($val[0])) {
  498. if(preg_match('/^(EQ|NEQ|GT|EGT|LT|ELT|NOTLIKE|LIKE)$/i',$val[0])) { // 比较运算
  499. $whereStr .= $key.' '.$this->comparison[strtolower($val[0])].' '.$this->parseValue($val[1]);
  500. }elseif('exp'==strtolower($val[0])){ // 使用表达式
  501. $whereStr .= ' ('.$key.' '.$val[1].') ';
  502. }elseif(preg_match('/IN/i',$val[0])){ // IN 运算
  503. $zone = is_array($val[1])? implode(',',$this->parseValue($val[1])):$val[1];
  504. $whereStr .= $key.' '.strtoupper($val[0]).' ('.$zone.')';
  505. }elseif(preg_match('/BETWEEN/i',$val[0])){ // BETWEEN运算
  506. $data = is_string($val[1])? explode(',',$val[1]):$val[1];
  507. $whereStr .= ' ('.$key.' BETWEEN '.$data[0].' AND '.$data[1].' )';
  508. }else{
  509. throw_exception(L('_EXPRESS_ERROR_').':'.$val[0]);
  510. }
  511. }else {
  512. $count = count($val);
  513. if(in_array(strtoupper(trim($val[$count-1])),array('AND','OR','XOR'))) {
  514. $rule = strtoupper(trim($val[$count-1]));
  515. $count = $count -1;
  516. }else{
  517. $rule = 'AND';
  518. }
  519. for($i=0;$i<$count;$i++) {
  520. $data = is_array($val[$i])?$val[$i][1]:$val[$i];
  521. if('exp'==strtolower($val[$i][0])) {
  522. $whereStr .= '('.$key.' '.$data.') '.$rule.' ';
  523. }else{
  524. $op = is_array($val[$i])?$this->comparison[strtolower($val[$i][0])]:'=';
  525. $whereStr .= '('.$key.' '.$op.' '.$this->parseValue($data).') '.$rule.' ';
  526. }
  527. }
  528. $whereStr = substr($whereStr,0,-4);
  529. }
  530. }else {
  531. //对字符串类型字段采用模糊匹配
  532. if(C('LIKE_MATCH_FIELDS') && preg_match('/('.C('LIKE_MATCH_FIELDS').')/i',$key)) {
  533. $val = '%'.$val.'%';
  534. $whereStr .= $key." LIKE ".$this->parseValue($val);
  535. }else {
  536. $whereStr .= $key." = ".$this->parseValue($val);
  537. }
  538. }
  539. }
  540. $whereStr .= ' )'.$operate;
  541. }
  542. $whereStr = substr($whereStr,0,-strlen($operate));
  543. }
  544. return empty($whereStr)?'':' WHERE '.$whereStr;
  545. }
  546. /**
  547. * 特殊条件分析
  548. * @access protected
  549. * @param string $key
  550. * @param mixed $val
  551. * @return string
  552. */
  553. protected function parseThinkWhere($key,$val) {
  554. $whereStr = '';
  555. switch($key) {
  556. case '_string':
  557. // 字符串模式查询条件
  558. $whereStr = $val;
  559. break;
  560. case '_complex':
  561. // 复合查询条件
  562. $whereStr = substr($this->parseWhere($val),6);
  563. break;
  564. case '_query':
  565. // 字符串模式查询条件
  566. parse_str($val,$where);
  567. if(isset($where['_logic'])) {
  568. $op = ' '.strtoupper($where['_logic']).' ';
  569. unset($where['_logic']);
  570. }else{
  571. $op = ' AND ';
  572. }
  573. $array = array();
  574. foreach ($where as $field=>$data)
  575. $array[] = $this->parseKey($field).' = '.$this->parseValue($data);
  576. $whereStr = implode($op,$array);
  577. break;
  578. }
  579. return $whereStr;
  580. }
  581. /**
  582. * limit分析
  583. * @access protected
  584. * @param mixed $lmit
  585. * @return string
  586. */
  587. protected function parseLimit($limit) {
  588. return !empty($limit)? ' LIMIT '.$limit.' ':'';
  589. }
  590. /**
  591. * join分析
  592. * @access protected
  593. * @param mixed $join
  594. * @return string
  595. */
  596. protected function parseJoin($join) {
  597. $joinStr = '';
  598. if(!empty($join)) {
  599. if(is_array($join)) {
  600. foreach ($join as $key=>$_join){
  601. if(false !== stripos($_join,'JOIN'))
  602. $joinStr .= ' '.$_join;
  603. else
  604. $joinStr .= ' LEFT JOIN ' .$_join;
  605. }
  606. }else{
  607. $joinStr .= ' LEFT JOIN ' .$join;
  608. }
  609. }
  610. return $joinStr;
  611. }
  612. /**
  613. * order分析
  614. * @access protected
  615. * @param mixed $order
  616. * @return string
  617. */
  618. protected function parseOrder($order) {
  619. return !empty($order)? ' ORDER BY '.$order:'';
  620. }
  621. /**
  622. * group分析
  623. * @access protected
  624. * @param mixed $group
  625. * @return string
  626. */
  627. protected function parseGroup($group) {
  628. return !empty($group)? ' GROUP BY '.$group:'';
  629. }
  630. /**
  631. * having分析
  632. * @access protected
  633. * @param string $having
  634. * @return string
  635. */
  636. protected function parseHaving($having) {
  637. return !empty($having)? ' HAVING '.$having:'';
  638. }
  639. /**
  640. * distinct分析
  641. * @access protected
  642. * @param mixed $distinct
  643. * @return string
  644. */
  645. protected function parseDistinct($distinct) {
  646. return !empty($distinct)? ' DISTINCT ' :'';
  647. }
  648. /**
  649. * 插入记录
  650. * @access public
  651. * @param mixed $data 数据
  652. * @param array $options 参数表达式
  653. * @return false | integer
  654. */
  655. public function insert($data,$options=array()) {
  656. foreach ($data as $key=>$val){
  657. $value = $this->parseValue($val);
  658. if(is_scalar($value)) { // 过滤非标量数据
  659. $values[] = $value;
  660. $fields[] = $this->parseKey($key);
  661. }
  662. }
  663. $sql = 'INSERT INTO '.$this->parseTable($options['table']).' ('.implode(',', $fields).') VALUES ('.implode(',', $values).')';
  664. $sql .= $this->parseLock(isset($options['lock'])?$options['lock']:false);
  665. return $this->execute($sql);
  666. }
  667. /**
  668. * 更新记录
  669. * @access public
  670. * @param mixed $data 数据
  671. * @param array $options 表达式
  672. * @return false | integer
  673. */
  674. public function update($data,$options) {
  675. $sql = 'UPDATE '
  676. .$this->parseTable($options['table'])
  677. .$this->parseSet($data)
  678. .$this->parseWhere(isset($options['where'])?$options['where']:'')
  679. .$this->parseOrder(isset($options['order'])?$options['order']:'')
  680. .$this->parseLimit(isset($options['limit'])?$options['limit']:'')
  681. .$this->parseLock(isset($options['lock'])?$options['lock']:false);
  682. return $this->execute($sql);
  683. }
  684. /**
  685. * 删除记录
  686. * @access public
  687. * @param array $options 表达式
  688. * @return false | integer
  689. */
  690. public function delete($options=array()) {
  691. $sql = 'DELETE FROM '
  692. .$this->parseTable($options['table'])
  693. .$this->parseWhere(isset($options['where'])?$options['where']:'')
  694. .$this->parseOrder(isset($options['order'])?$options['order']:'')
  695. .$this->parseLimit(isset($options['limit'])?$options['limit']:'')
  696. .$this->parseLock(isset($options['lock'])?$options['lock']:false);
  697. return $this->execute($sql);
  698. }
  699. /**
  700. * 查找记录
  701. * @access public
  702. * @param array $options 表达式
  703. * @return array
  704. */
  705. public function select($options=array()) {
  706. if(isset($options['page'])) {
  707. // 根据页数计算limit
  708. list($page,$listRows) = explode(',',$options['page']);
  709. $listRows = $listRows?$listRows:($options['limit']?$options['limit']:20);
  710. $offset = $listRows*((int)$page-1);
  711. $options['limit'] = $offset.','.$listRows;
  712. }
  713. $sql = str_replace(
  714. array('%TABLE%','%DISTINCT%','%FIELDS%','%JOIN%','%WHERE%','%GROUP%','%HAVING%','%ORDER%','%LIMIT%'),
  715. array(
  716. $this->parseTable($options['table']),
  717. $this->parseDistinct(isset($options['distinct'])?$options['distinct']:false),
  718. $this->parseField(isset($options['field'])?$options['field']:'*'),
  719. $this->parseJoin(isset($options['join'])?$options['join']:''),
  720. $this->parseWhere(isset($options['where'])?$options['where']:''),
  721. $this->parseGroup(isset($options['group'])?$options['group']:''),
  722. $this->parseHaving(isset($options['having'])?$options['having']:''),
  723. $this->parseOrder(isset($options['order'])?$options['order']:''),
  724. $this->parseLimit(isset($options['limit'])?$options['limit']:'')
  725. ),$this->selectSql);
  726. $sql .= $this->parseLock(isset($options['lock'])?$options['lock']:false);
  727. return $this->query($sql);
  728. }
  729. /**
  730. * 字段和表名添加`
  731. * 保证指令中使用关键字不出错 针对mysql
  732. * @access protected
  733. * @param mixed $value
  734. * @return mixed
  735. */
  736. protected function parseKey(&$value) {
  737. $value = trim($value);
  738. if( false !== strpos($value,' ') || false !== strpos($value,',') || false !== strpos($value,'*') || false !== strpos($value,'(') || false !== strpos($value,'.') || false !== strpos($value,'`')) {
  739. //如果包含* 或者 使用了sql方法 则不作处理
  740. }else{
  741. $value = '`'.$value.'`';
  742. }
  743. return $value;
  744. }
  745. /**
  746. * 获取最近一次查询的sql语句
  747. * @access public
  748. * @return string
  749. */
  750. public function getLastSql() {
  751. return $this->queryStr;
  752. }
  753. /**
  754. * 获取最近插入的ID
  755. * @access public
  756. * @return string
  757. */
  758. public function getLastInsID(){
  759. return $this->lastInsID;
  760. }
  761. }