Db.class.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  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. if ($this->transTimes > 0) {
  181. $result = mysql_query('COMMIT', $this->linkID);
  182. $this->transTimes = 0;
  183. if(!$result){
  184. throw_exception($this->error());
  185. return false;
  186. }
  187. }
  188. return true;
  189. }
  190. /**
  191. * 事务回滚
  192. * @access public
  193. * @return boolen
  194. * @throws ThinkExecption
  195. */
  196. public function rollback() {
  197. if ($this->transTimes > 0) {
  198. $result = mysql_query('ROLLBACK', $this->linkID);
  199. $this->transTimes = 0;
  200. if(!$result){
  201. throw_exception($this->error());
  202. return false;
  203. }
  204. }
  205. return true;
  206. }
  207. /**
  208. * 获得所有的查询数据
  209. * @access public
  210. * @return array
  211. * @throws ThinkExecption
  212. */
  213. public function getAll() {
  214. if ( !$this->queryID ) {
  215. throw_exception($this->error());
  216. return false;
  217. }
  218. //返回数据集
  219. $result = array();
  220. if($this->numRows >0) {
  221. while($row = mysql_fetch_assoc($this->queryID)){
  222. $result[] = $row;
  223. }
  224. mysql_data_seek($this->queryID,0);
  225. }
  226. return $result;
  227. }
  228. /**
  229. * 取得数据表的字段信息
  230. * @access public
  231. */
  232. public function getFields($tableName) {
  233. $result = $this->query('SHOW COLUMNS FROM '.$tableName);
  234. $info = array();
  235. foreach ($result as $key => $val) {
  236. $info[$val['Field']] = array(
  237. 'name' => $val['Field'],
  238. 'type' => $val['Type'],
  239. 'notnull' => (bool) ($val['Null'] === ''), // not null is empty, null is yes
  240. 'default' => $val['Default'],
  241. 'primary' => (strtolower($val['Key']) == 'pri'),
  242. 'autoinc' => (strtolower($val['Extra']) == 'auto_increment'),
  243. );
  244. }
  245. return $info;
  246. }
  247. /**
  248. * 取得数据库的表信息
  249. * @access public
  250. */
  251. public function getTables($dbName='') {
  252. if(!empty($dbName)) {
  253. $sql = 'SHOW TABLES FROM '.$dbName;
  254. }else{
  255. $sql = 'SHOW TABLES ';
  256. }
  257. $result = $this->query($sql);
  258. $info = array();
  259. foreach ($result as $key => $val) {
  260. $info[$key] = current($val);
  261. }
  262. return $info;
  263. }
  264. /**
  265. * 关闭数据库
  266. * @access public
  267. * @throws ThinkExecption
  268. */
  269. public function close() {
  270. if (!empty($this->queryID))
  271. mysql_free_result($this->queryID);
  272. if ($this->linkID && !mysql_close($this->linkID)){
  273. throw_exception($this->error());
  274. }
  275. $this->linkID = 0;
  276. }
  277. /**
  278. * 数据库错误信息
  279. * 并显示当前的SQL语句
  280. * @access public
  281. * @return string
  282. */
  283. public function error() {
  284. $this->error = mysql_error($this->linkID);
  285. if($this->queryStr!=''){
  286. $this->error .= "\n [ SQL语句 ] : ".$this->queryStr;
  287. }
  288. return $this->error;
  289. }
  290. /**
  291. * SQL指令安全过滤
  292. * @access public
  293. * @param string $str SQL字符串
  294. * @return string
  295. */
  296. public function escape_string($str) {
  297. return mysql_escape_string($str);
  298. }
  299. /**
  300. * 析构方法
  301. * @access public
  302. */
  303. public function __destruct() {
  304. // 关闭连接
  305. $this->close();
  306. }
  307. /**
  308. * 取得数据库类实例
  309. * @static
  310. * @access public
  311. * @return mixed 返回数据库驱动类
  312. */
  313. public static function getInstance($db_config='') {
  314. if ( self::$_instance==null ){
  315. self::$_instance = new Db($db_config);
  316. }
  317. return self::$_instance;
  318. }
  319. /**
  320. * 分析数据库配置信息,支持数组和DSN
  321. * @access private
  322. * @param mixed $db_config 数据库配置信息
  323. * @return string
  324. */
  325. private function parseConfig($db_config='') {
  326. if ( !empty($db_config) && is_string($db_config)) {
  327. // 如果DSN字符串则进行解析
  328. $db_config = $this->parseDSN($db_config);
  329. }else if(empty($db_config)){
  330. // 如果配置为空,读取配置文件设置
  331. $db_config = array (
  332. 'dbms' => C('DB_TYPE'),
  333. 'username' => C('DB_USER'),
  334. 'password' => C('DB_PWD'),
  335. 'hostname' => C('DB_HOST'),
  336. 'hostport' => C('DB_PORT'),
  337. 'database' => C('DB_NAME'),
  338. 'dsn' => C('DB_DSN'),
  339. 'params' => C('DB_PARAMS'),
  340. );
  341. }
  342. return $db_config;
  343. }
  344. /**
  345. * DSN解析
  346. * 格式: mysql://username:passwd@localhost:3306/DbName
  347. * @static
  348. * @access public
  349. * @param string $dsnStr
  350. * @return array
  351. */
  352. public function parseDSN($dsnStr) {
  353. if( empty($dsnStr) ){return false;}
  354. $info = parse_url($dsnStr);
  355. if($info['scheme']){
  356. $dsn = array(
  357. 'dbms' => $info['scheme'],
  358. 'username' => isset($info['user']) ? $info['user'] : '',
  359. 'password' => isset($info['pass']) ? $info['pass'] : '',
  360. 'hostname' => isset($info['host']) ? $info['host'] : '',
  361. 'hostport' => isset($info['port']) ? $info['port'] : '',
  362. 'database' => isset($info['path']) ? substr($info['path'],1) : ''
  363. );
  364. }else {
  365. preg_match('/^(.*?)\:\/\/(.*?)\:(.*?)\@(.*?)\:([0-9]{1, 6})\/(.*?)$/',trim($dsnStr),$matches);
  366. $dsn = array (
  367. 'dbms' => $matches[1],
  368. 'username' => $matches[2],
  369. 'password' => $matches[3],
  370. 'hostname' => $matches[4],
  371. 'hostport' => $matches[5],
  372. 'database' => $matches[6]
  373. );
  374. }
  375. return $dsn;
  376. }
  377. /**
  378. * 数据库调试 记录当前SQL
  379. * @access protected
  380. */
  381. protected function debug() {
  382. // 记录操作结束时间
  383. if ( $this->debug ) {
  384. G('queryEndTime');
  385. Log::record($this->queryStr." [ RunTime:".G('queryStartTime','queryEndTime',6)."s ]",Log::SQL);
  386. }
  387. }
  388. /**
  389. * 设置锁机制
  390. * @access protected
  391. * @return string
  392. */
  393. protected function parseLock($lock=false) {
  394. if(!$lock) return '';
  395. if('ORACLE' == $this->dbType) {
  396. return ' FOR UPDATE NOWAIT ';
  397. }
  398. return ' FOR UPDATE ';
  399. }
  400. /**
  401. * set分析
  402. * @access protected
  403. * @param array $data
  404. * @return string
  405. */
  406. protected function parseSet($data) {
  407. foreach ($data as $key=>$val){
  408. $value = $this->parseValue($val);
  409. if(is_scalar($value)) // 过滤非标量数据
  410. $set[] = $this->parseKey($key).'='.$value;
  411. }
  412. return ' SET '.implode(',',$set);
  413. }
  414. /**
  415. * value分析
  416. * @access protected
  417. * @param mixed $value
  418. * @return string
  419. */
  420. protected function parseValue($value) {
  421. if(is_string($value)) {
  422. $value = '\''.$this->escape_string($value).'\'';
  423. }elseif(isset($value[0]) && is_string($value[0]) && strtolower($value[0]) == 'exp'){
  424. $value = $this->escape_string($value[1]);
  425. }elseif(is_null($value)){
  426. $value = 'null';
  427. }
  428. return $value;
  429. }
  430. /**
  431. * field分析
  432. * @access protected
  433. * @param mixed $fields
  434. * @return string
  435. */
  436. protected function parseField($fields) {
  437. if(is_array($fields)) {
  438. // 完善数组方式传字段名的支持
  439. // 支持 'field1'=>'field2' 这样的字段别名定义
  440. $array = array();
  441. foreach ($fields as $key=>$field){
  442. if(!is_numeric($key))
  443. $array[] = $this->parseKey($key).' AS '.$this->parseKey($field);
  444. else
  445. $array[] = $this->parseKey($field);
  446. }
  447. $fieldsStr = implode(',', $array);
  448. }elseif(is_string($fields) && !empty($fields)) {
  449. $fieldsStr = $this->parseKey($fields);
  450. }else{
  451. $fieldsStr = '*';
  452. }
  453. return $fieldsStr;
  454. }
  455. /**
  456. * table分析
  457. * @access protected
  458. * @param mixed $table
  459. * @return string
  460. */
  461. protected function parseTable($tables) {
  462. if(is_string($tables))
  463. $tables = explode(',',$tables);
  464. array_walk($tables, array(&$this, 'parseKey'));
  465. return implode(',',$tables);
  466. }
  467. /**
  468. * where分析
  469. * @access protected
  470. * @param mixed $where
  471. * @return string
  472. */
  473. protected function parseWhere($where) {
  474. $whereStr = '';
  475. if(is_string($where)) {
  476. // 直接使用字符串条件
  477. $whereStr = $where;
  478. }else{ // 使用数组条件表达式
  479. if(isset($where['_logic'])) {
  480. // 定义逻辑运算规则 例如 OR XOR AND NOT
  481. $operate = ' '.strtoupper($where['_logic']).' ';
  482. unset($where['_logic']);
  483. }else{
  484. // 默认进行 AND 运算
  485. $operate = ' AND ';
  486. }
  487. foreach ($where as $key=>$val){
  488. $whereStr .= "( ";
  489. if(0===strpos($key,'_')) {
  490. // 解析特殊条件表达式
  491. $whereStr .= $this->parseThinkWhere($key,$val);
  492. }else{
  493. $key = $this->parseKey($key);
  494. if(is_array($val)) {
  495. if(is_string($val[0])) {
  496. if(preg_match('/^(EQ|NEQ|GT|EGT|LT|ELT|NOTLIKE|LIKE)$/i',$val[0])) { // 比较运算
  497. $whereStr .= $key.' '.$this->comparison[strtolower($val[0])].' '.$this->parseValue($val[1]);
  498. }elseif('exp'==strtolower($val[0])){ // 使用表达式
  499. $whereStr .= ' ('.$key.' '.$val[1].') ';
  500. }elseif(preg_match('/IN/i',$val[0])){ // IN 运算
  501. $zone = is_array($val[1])? implode(',',$this->parseValue($val[1])):$val[1];
  502. $whereStr .= $key.' '.strtoupper($val[0]).' ('.$zone.')';
  503. }elseif(preg_match('/BETWEEN/i',$val[0])){ // BETWEEN运算
  504. $data = is_string($val[1])? explode(',',$val[1]):$val[1];
  505. $whereStr .= ' ('.$key.' BETWEEN '.$data[0].' AND '.$data[1].' )';
  506. }else{
  507. throw_exception(L('_EXPRESS_ERROR_').':'.$val[0]);
  508. }
  509. }else {
  510. $count = count($val);
  511. if(in_array(strtoupper(trim($val[$count-1])),array('AND','OR','XOR'))) {
  512. $rule = strtoupper(trim($val[$count-1]));
  513. $count = $count -1;
  514. }else{
  515. $rule = 'AND';
  516. }
  517. for($i=0;$i<$count;$i++) {
  518. $data = is_array($val[$i])?$val[$i][1]:$val[$i];
  519. if('exp'==strtolower($val[$i][0])) {
  520. $whereStr .= '('.$key.' '.$data.') '.$rule.' ';
  521. }else{
  522. $op = is_array($val[$i])?$this->comparison[strtolower($val[$i][0])]:'=';
  523. $whereStr .= '('.$key.' '.$op.' '.$this->parseValue($data).') '.$rule.' ';
  524. }
  525. }
  526. $whereStr = substr($whereStr,0,-4);
  527. }
  528. }else {
  529. //对字符串类型字段采用模糊匹配
  530. if(C('LIKE_MATCH_FIELDS') && preg_match('/('.C('LIKE_MATCH_FIELDS').')/i',$key)) {
  531. $val = '%'.$val.'%';
  532. $whereStr .= $key." LIKE ".$this->parseValue($val);
  533. }else {
  534. $whereStr .= $key." = ".$this->parseValue($val);
  535. }
  536. }
  537. }
  538. $whereStr .= ' )'.$operate;
  539. }
  540. $whereStr = substr($whereStr,0,-strlen($operate));
  541. }
  542. return empty($whereStr)?'':' WHERE '.$whereStr;
  543. }
  544. /**
  545. * 特殊条件分析
  546. * @access protected
  547. * @param string $key
  548. * @param mixed $val
  549. * @return string
  550. */
  551. protected function parseThinkWhere($key,$val) {
  552. $whereStr = '';
  553. switch($key) {
  554. case '_string':
  555. // 字符串模式查询条件
  556. $whereStr = $val;
  557. break;
  558. case '_complex':
  559. // 复合查询条件
  560. $whereStr = substr($this->parseWhere($val),6);
  561. break;
  562. case '_query':
  563. // 字符串模式查询条件
  564. parse_str($val,$where);
  565. if(isset($where['_logic'])) {
  566. $op = ' '.strtoupper($where['_logic']).' ';
  567. unset($where['_logic']);
  568. }else{
  569. $op = ' AND ';
  570. }
  571. $array = array();
  572. foreach ($where as $field=>$data)
  573. $array[] = $this->parseKey($field).' = '.$this->parseValue($data);
  574. $whereStr = implode($op,$array);
  575. break;
  576. }
  577. return $whereStr;
  578. }
  579. /**
  580. * limit分析
  581. * @access protected
  582. * @param mixed $lmit
  583. * @return string
  584. */
  585. protected function parseLimit($limit) {
  586. return !empty($limit)? ' LIMIT '.$limit.' ':'';
  587. }
  588. /**
  589. * join分析
  590. * @access protected
  591. * @param mixed $join
  592. * @return string
  593. */
  594. protected function parseJoin($join) {
  595. $joinStr = '';
  596. if(!empty($join)) {
  597. if(is_array($join)) {
  598. foreach ($join as $key=>$_join){
  599. if(false !== stripos($_join,'JOIN'))
  600. $joinStr .= ' '.$_join;
  601. else
  602. $joinStr .= ' LEFT JOIN ' .$_join;
  603. }
  604. }else{
  605. $joinStr .= ' LEFT JOIN ' .$join;
  606. }
  607. }
  608. return $joinStr;
  609. }
  610. /**
  611. * order分析
  612. * @access protected
  613. * @param mixed $order
  614. * @return string
  615. */
  616. protected function parseOrder($order) {
  617. return !empty($order)? ' ORDER BY '.$order:'';
  618. }
  619. /**
  620. * group分析
  621. * @access protected
  622. * @param mixed $group
  623. * @return string
  624. */
  625. protected function parseGroup($group) {
  626. return !empty($group)? ' GROUP BY '.$group:'';
  627. }
  628. /**
  629. * having分析
  630. * @access protected
  631. * @param string $having
  632. * @return string
  633. */
  634. protected function parseHaving($having) {
  635. return !empty($having)? ' HAVING '.$having:'';
  636. }
  637. /**
  638. * distinct分析
  639. * @access protected
  640. * @param mixed $distinct
  641. * @return string
  642. */
  643. protected function parseDistinct($distinct) {
  644. return !empty($distinct)? ' DISTINCT ' :'';
  645. }
  646. /**
  647. * 插入记录
  648. * @access public
  649. * @param mixed $data 数据
  650. * @param array $options 参数表达式
  651. * @return false | integer
  652. */
  653. public function insert($data,$options=array()) {
  654. foreach ($data as $key=>$val){
  655. $value = $this->parseValue($val);
  656. if(is_scalar($value)) { // 过滤非标量数据
  657. $values[] = $value;
  658. $fields[] = $this->parseKey($key);
  659. }
  660. }
  661. $sql = 'INSERT INTO '.$this->parseTable($options['table']).' ('.implode(',', $fields).') VALUES ('.implode(',', $values).')';
  662. $sql .= $this->parseLock(isset($options['lock'])?$options['lock']:false);
  663. return $this->execute($sql);
  664. }
  665. /**
  666. * 更新记录
  667. * @access public
  668. * @param mixed $data 数据
  669. * @param array $options 表达式
  670. * @return false | integer
  671. */
  672. public function update($data,$options) {
  673. $sql = 'UPDATE '
  674. .$this->parseTable($options['table'])
  675. .$this->parseSet($data)
  676. .$this->parseWhere(isset($options['where'])?$options['where']:'')
  677. .$this->parseOrder(isset($options['order'])?$options['order']:'')
  678. .$this->parseLimit(isset($options['limit'])?$options['limit']:'')
  679. .$this->parseLock(isset($options['lock'])?$options['lock']:false);
  680. return $this->execute($sql);
  681. }
  682. /**
  683. * 删除记录
  684. * @access public
  685. * @param array $options 表达式
  686. * @return false | integer
  687. */
  688. public function delete($options=array()) {
  689. $sql = 'DELETE FROM '
  690. .$this->parseTable($options['table'])
  691. .$this->parseWhere(isset($options['where'])?$options['where']:'')
  692. .$this->parseOrder(isset($options['order'])?$options['order']:'')
  693. .$this->parseLimit(isset($options['limit'])?$options['limit']:'')
  694. .$this->parseLock(isset($options['lock'])?$options['lock']:false);
  695. return $this->execute($sql);
  696. }
  697. /**
  698. * 查找记录
  699. * @access public
  700. * @param array $options 表达式
  701. * @return array
  702. */
  703. public function select($options=array()) {
  704. if(isset($options['page'])) {
  705. // 根据页数计算limit
  706. list($page,$listRows) = explode(',',$options['page']);
  707. $listRows = $listRows?$listRows:($options['limit']?$options['limit']:20);
  708. $offset = $listRows*((int)$page-1);
  709. $options['limit'] = $offset.','.$listRows;
  710. }
  711. $sql = str_replace(
  712. array('%TABLE%','%DISTINCT%','%FIELDS%','%JOIN%','%WHERE%','%GROUP%','%HAVING%','%ORDER%','%LIMIT%'),
  713. array(
  714. $this->parseTable($options['table']),
  715. $this->parseDistinct(isset($options['distinct'])?$options['distinct']:false),
  716. $this->parseField(isset($options['field'])?$options['field']:'*'),
  717. $this->parseJoin(isset($options['join'])?$options['join']:''),
  718. $this->parseWhere(isset($options['where'])?$options['where']:''),
  719. $this->parseGroup(isset($options['group'])?$options['group']:''),
  720. $this->parseHaving(isset($options['having'])?$options['having']:''),
  721. $this->parseOrder(isset($options['order'])?$options['order']:''),
  722. $this->parseLimit(isset($options['limit'])?$options['limit']:'')
  723. ),$this->selectSql);
  724. $sql .= $this->parseLock(isset($options['lock'])?$options['lock']:false);
  725. return $this->query($sql);
  726. }
  727. /**
  728. * 字段和表名添加`
  729. * 保证指令中使用关键字不出错 针对mysql
  730. * @access protected
  731. * @param mixed $value
  732. * @return mixed
  733. */
  734. protected function parseKey(&$value) {
  735. $value = trim($value);
  736. if( false !== strpos($value,' ') || false !== strpos($value,',') || false !== strpos($value,'*') || false !== strpos($value,'(') || false !== strpos($value,'.') || false !== strpos($value,'`')) {
  737. //如果包含* 或者 使用了sql方法 则不作处理
  738. }else{
  739. $value = '`'.$value.'`';
  740. }
  741. return $value;
  742. }
  743. /**
  744. * 获取最近一次查询的sql语句
  745. * @access public
  746. * @return string
  747. */
  748. public function getLastSql() {
  749. return $this->queryStr;
  750. }
  751. /**
  752. * 获取最近插入的ID
  753. * @access public
  754. * @return string
  755. */
  756. public function getLastInsID(){
  757. return $this->lastInsID;
  758. }
  759. }