Db.class.php 26 KB

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