PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/classes/db/DBMysqli.class.php

http://xe-core.googlecode.com/
PHP | 447 lines | 283 code | 42 blank | 122 comment | 39 complexity | efdb1eb099745698ad3a9f6308504b34 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause
  1. <?php
  2. require_once('DBMysql.class.php');
  3. /**
  4. * Class to use MySQLi DBMS as mysqli_*
  5. * mysql handling class
  6. *
  7. * Does not use prepared statements, since mysql driver does not support them
  8. *
  9. * @author NHN (developers@xpressengine.com)
  10. * @package /classes/db
  11. * @version 0.1
  12. */
  13. class DBMysqli extends DBMysql
  14. {
  15. /**
  16. * Constructor
  17. * @return void
  18. */
  19. function DBMysqli()
  20. {
  21. $this->_setDBInfo();
  22. $this->_connect();
  23. }
  24. /**
  25. * Return if supportable
  26. * Check 'mysqli_connect' function exists.
  27. * @return boolean
  28. */
  29. function isSupported()
  30. {
  31. if(!function_exists('mysqli_connect'))
  32. {
  33. return false;
  34. }
  35. return true;
  36. }
  37. /**
  38. * Create an instance of this class
  39. * @return DBMysqli return DBMysqli object instance
  40. */
  41. function create()
  42. {
  43. return new DBMysqli;
  44. }
  45. /**
  46. * DB Connect
  47. * this method is private
  48. * @param array $connection connection's value is db_hostname, db_port, db_database, db_userid, db_password
  49. * @return resource
  50. */
  51. function __connect($connection)
  52. {
  53. // Attempt to connect
  54. if($connection["db_port"])
  55. {
  56. $result = @mysqli_connect($connection["db_hostname"]
  57. , $connection["db_userid"]
  58. , $connection["db_password"]
  59. , $connection["db_database"]
  60. , $connection["db_port"]);
  61. }
  62. else
  63. {
  64. $result = @mysqli_connect($connection["db_hostname"]
  65. , $connection["db_userid"]
  66. , $connection["db_password"]
  67. , $connection["db_database"]);
  68. }
  69. $error = mysqli_connect_errno();
  70. if($error)
  71. {
  72. $this->setError($error, mysqli_connect_error());
  73. return;
  74. }
  75. mysqli_set_charset($result, 'utf8');
  76. return $result;
  77. }
  78. /**
  79. * DB disconnection
  80. * this method is private
  81. * @param resource $connection
  82. * @return void
  83. */
  84. function _close($connection)
  85. {
  86. mysqli_close($connection);
  87. }
  88. /**
  89. * Handles quatation of the string variables from the query
  90. * @param string $string
  91. * @return string
  92. */
  93. function addQuotes($string)
  94. {
  95. if(version_compare(PHP_VERSION, "5.9.0", "<") && get_magic_quotes_gpc())
  96. {
  97. $string = stripslashes(str_replace("\\", "\\\\", $string));
  98. }
  99. if(!is_numeric($string))
  100. {
  101. $connection = $this->_getConnection('master');
  102. $string = mysqli_escape_string($connection, $string);
  103. }
  104. return $string;
  105. }
  106. /**
  107. * Execute the query
  108. * this method is private
  109. * @param string $query
  110. * @param resource $connection
  111. * @return resource
  112. */
  113. function __query($query, $connection)
  114. {
  115. if($this->use_prepared_statements == 'Y')
  116. {
  117. // 1. Prepare query
  118. $stmt = mysqli_prepare($connection, $query);
  119. if($stmt)
  120. {
  121. $types = '';
  122. $params = array();
  123. $this->_prepareQueryParameters($types, $params);
  124. if(!empty($params))
  125. {
  126. $args[0] = $stmt;
  127. $args[1] = $types;
  128. $i = 2;
  129. foreach($params as $key => $param)
  130. {
  131. $copy[$key] = $param;
  132. $args[$i++] = &$copy[$key];
  133. }
  134. // 2. Bind parameters
  135. $status = call_user_func_array('mysqli_stmt_bind_param', $args);
  136. if(!$status)
  137. {
  138. $this->setError(-1, "Invalid arguments: $query" . mysqli_error($connection) . PHP_EOL . print_r($args, true));
  139. }
  140. }
  141. // 3. Execute query
  142. $status = mysqli_stmt_execute($stmt);
  143. if(!$status)
  144. {
  145. $this->setError(-1, "Prepared statement failed: $query" . mysqli_error($connection) . PHP_EOL . print_r($args, true));
  146. }
  147. // Return stmt for other processing - like retrieving resultset (_fetch)
  148. return $stmt;
  149. // mysqli_stmt_close($stmt);
  150. }
  151. }
  152. // Run the query statement
  153. $result = mysqli_query($connection, $query);
  154. // Error Check
  155. $error = mysqli_error($connection);
  156. if($error)
  157. {
  158. $this->setError(mysqli_errno($connection), $error);
  159. }
  160. // Return result
  161. return $result;
  162. }
  163. /**
  164. * Before execute query, prepare statement
  165. * this method is private
  166. * @param string $types
  167. * @param array $params
  168. * @return void
  169. */
  170. function _prepareQueryParameters(&$types, &$params)
  171. {
  172. $types = '';
  173. $params = array();
  174. if(!$this->param)
  175. {
  176. return;
  177. }
  178. foreach($this->param as $k => $o)
  179. {
  180. $value = $o->getUnescapedValue();
  181. $type = $o->getType();
  182. // Skip column names -> this should be concatenated to query string
  183. if($o->isColumnName())
  184. {
  185. continue;
  186. }
  187. switch($type)
  188. {
  189. case 'number' :
  190. $type = 'i';
  191. break;
  192. case 'varchar' :
  193. $type = 's';
  194. break;
  195. default:
  196. $type = 's';
  197. }
  198. if(is_array($value))
  199. {
  200. foreach($value as $v)
  201. {
  202. $params[] = $v;
  203. $types .= $type;
  204. }
  205. }
  206. else
  207. {
  208. $params[] = $value;
  209. $types .= $type;
  210. }
  211. }
  212. }
  213. /**
  214. * Fetch the result
  215. * @param resource $result
  216. * @param int|NULL $arrayIndexEndValue
  217. * @return array
  218. */
  219. function _fetch($result, $arrayIndexEndValue = NULL)
  220. {
  221. if($this->use_prepared_statements != 'Y')
  222. {
  223. return parent::_fetch($result, $arrayIndexEndValue);
  224. }
  225. $output = array();
  226. if(!$this->isConnected() || $this->isError() || !$result)
  227. {
  228. return $output;
  229. }
  230. // Prepared stements: bind result variable and fetch data
  231. $stmt = $result;
  232. $meta = mysqli_stmt_result_metadata($stmt);
  233. $fields = mysqli_fetch_fields($meta);
  234. /**
  235. * Mysqli has a bug that causes LONGTEXT columns not to get loaded
  236. * Unless store_result is called before
  237. * MYSQLI_TYPE for longtext is 252
  238. */
  239. $longtext_exists = false;
  240. foreach($fields as $field)
  241. {
  242. if(isset($resultArray[$field->name])) // When joined tables are used and the same column name appears twice, we should add it separately, otherwise bind_result fails
  243. {
  244. $field->name = 'repeat_' . $field->name;
  245. }
  246. // Array passed needs to contain references, not values
  247. $row[$field->name] = "";
  248. $resultArray[$field->name] = &$row[$field->name];
  249. if($field->type == 252)
  250. {
  251. $longtext_exists = true;
  252. }
  253. }
  254. $resultArray = array_merge(array($stmt), $resultArray);
  255. if($longtext_exists)
  256. {
  257. mysqli_stmt_store_result($stmt);
  258. }
  259. call_user_func_array('mysqli_stmt_bind_result', $resultArray);
  260. $rows = array();
  261. while(mysqli_stmt_fetch($stmt))
  262. {
  263. $resultObject = new stdClass();
  264. foreach($resultArray as $key => $value)
  265. {
  266. if($key === 0)
  267. {
  268. continue; // Skip stmt object
  269. }
  270. if(strpos($key, 'repeat_'))
  271. {
  272. $key = substr($key, 6);
  273. }
  274. $resultObject->$key = $value;
  275. }
  276. $rows[] = $resultObject;
  277. }
  278. mysqli_stmt_close($stmt);
  279. if($arrayIndexEndValue)
  280. {
  281. foreach($rows as $row)
  282. {
  283. $output[$arrayIndexEndValue--] = $row;
  284. }
  285. }
  286. else
  287. {
  288. $output = $rows;
  289. }
  290. if(count($output) == 1)
  291. {
  292. if(isset($arrayIndexEndValue))
  293. {
  294. return $output;
  295. }
  296. else
  297. {
  298. return $output[0];
  299. }
  300. }
  301. return $output;
  302. }
  303. /**
  304. * Handles insertAct
  305. * @param Object $queryObject
  306. * @param boolean $with_values
  307. * @return resource
  308. */
  309. function _executeInsertAct($queryObject, $with_values = false)
  310. {
  311. if($this->use_prepared_statements != 'Y')
  312. {
  313. return parent::_executeInsertAct($queryObject);
  314. }
  315. $this->param = $queryObject->getArguments();
  316. $result = parent::_executeInsertAct($queryObject, $with_values);
  317. unset($this->param);
  318. return $result;
  319. }
  320. /**
  321. * Handles updateAct
  322. * @param Object $queryObject
  323. * @param boolean $with_values
  324. * @return resource
  325. */
  326. function _executeUpdateAct($queryObject, $with_values = false)
  327. {
  328. if($this->use_prepared_statements != 'Y')
  329. {
  330. return parent::_executeUpdateAct($queryObject);
  331. }
  332. $this->param = $queryObject->getArguments();
  333. $result = parent::_executeUpdateAct($queryObject, $with_values);
  334. unset($this->param);
  335. return $result;
  336. }
  337. /**
  338. * Handles deleteAct
  339. * @param Object $queryObject
  340. * @param boolean $with_values
  341. * @return resource
  342. */
  343. function _executeDeleteAct($queryObject, $with_values = false)
  344. {
  345. if($this->use_prepared_statements != 'Y')
  346. {
  347. return parent::_executeDeleteAct($queryObject);
  348. }
  349. $this->param = $queryObject->getArguments();
  350. $result = parent::_executeDeleteAct($queryObject, $with_values);
  351. unset($this->param);
  352. return $result;
  353. }
  354. /**
  355. * Handle selectAct
  356. * In order to get a list of pages easily when selecting \n
  357. * it supports a method as navigation
  358. * @param Object $queryObject
  359. * @param resource $connection
  360. * @param boolean $with_values
  361. * @return Object
  362. */
  363. function _executeSelectAct($queryObject, $connection = null, $with_values = false)
  364. {
  365. if($this->use_prepared_statements != 'Y')
  366. {
  367. return parent::_executeSelectAct($queryObject, $connection);
  368. }
  369. $this->param = $queryObject->getArguments();
  370. $result = parent::_executeSelectAct($queryObject, $connection, $with_values);
  371. unset($this->param);
  372. return $result;
  373. }
  374. /**
  375. * Get the ID generated in the last query
  376. * Return next sequence from sequence table
  377. * This method use only mysql
  378. * @return int
  379. */
  380. function db_insert_id()
  381. {
  382. $connection = $this->_getConnection('master');
  383. return mysqli_insert_id($connection);
  384. }
  385. /**
  386. * Fetch a result row as an object
  387. * @param resource $result
  388. * @return object
  389. */
  390. function db_fetch_object(&$result)
  391. {
  392. return mysqli_fetch_object($result);
  393. }
  394. /**
  395. * Free result memory
  396. * @param resource $result
  397. * @return boolean Returns TRUE on success or FALSE on failure.
  398. */
  399. function db_free_result(&$result)
  400. {
  401. return mysqli_free_result($result);
  402. }
  403. }
  404. /* End of file DBMysqli.class.php */
  405. /* Location: ./classes/db/DBMysqli.class.php */