1
0

sql.class.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. <?php
  2. /**
  3. * SQL class. Used for handling SQL connections
  4. *
  5. * @module sql
  6. * @class SQL
  7. * @constructor
  8. */
  9. class SQL {
  10. /**
  11. * This is the mysqli connection beneath everything
  12. *
  13. * @property sql
  14. * @type {mysqli}
  15. * @private
  16. * @required
  17. */
  18. private $sql;
  19. public $queries = [];
  20. private static $connections = [];
  21. public function __construct($server,$user,$pass,$db){
  22. $this->sql = new mysqli('p:'.$server,$user,$pass,$db) or die('Unable to connect to mysql');
  23. self::$connections[] = $sql;
  24. }
  25. public function __destruct(){
  26. $this->sql->rollback();
  27. $this->sql->close();
  28. foreach($this->queries as $query){
  29. unset($query);
  30. }
  31. self::$connections = array_diff(self::$connections, [$this]);
  32. }
  33. public function __invoke(){
  34. return $this->sql;
  35. }
  36. public function __get($name){
  37. switch($name){
  38. case 'error':
  39. return $this->sql->error;
  40. break;
  41. case 'insert_id':
  42. return $this->sql->insert_id;
  43. break;
  44. }
  45. }
  46. /**
  47. * Returns a Query object based on inputs
  48. *
  49. * @method query
  50. * @param {String} sql The sql expression to run
  51. * @param {String=null} [types] A string containing all the types of arguments being passed
  52. * @param {Mixed} [bindings]* The bindings to use in the sql statement
  53. * @return {Query} Returns the query object
  54. */
  55. public function query(...$args){
  56. return new Query(...array_merge([$this], $args));
  57. }
  58. public function escape($s){
  59. return $this->sql->escape_string($s);
  60. }
  61. public function charset($charset){
  62. return $this->sql->set_charset($charset);
  63. }
  64. public static function make_referenced(&$arr){
  65. $refs = [];
  66. foreach($arr as $key => $value){
  67. $refs[$key] = &$arr[$key];
  68. }
  69. return $refs;
  70. }
  71. public static function shutdown(){
  72. foreach(self::$connections as $sql){
  73. unset($sql);
  74. }
  75. }
  76. }
  77. /**
  78. * Query class. Returned by SQL::query()
  79. *
  80. * @class Query
  81. * @constructor
  82. */
  83. class Query {
  84. private $query;
  85. private $sql;
  86. private $_result = false;
  87. public function __construct($sql, $source, $types=null, ...$args){
  88. $sql->queries[] = $this;
  89. $args = array_merge([$types], $args);
  90. $this->sql = $sql();
  91. $this->query = $this->sql->prepare($source);
  92. if(!is_null($types)){
  93. if(!$this->query->bind_param(...SQL::make_referenced($args))){
  94. throw new Exception("Unable to bind parameter {$this->query->error}");
  95. }
  96. }
  97. }
  98. public function __destruct(){
  99. if($this->_result){
  100. $this->_result = false;
  101. $this->query->free_result();
  102. }
  103. if($this->query){
  104. $this->query->close();
  105. }
  106. $sql->queries = array_diff($sql->queries, [$this]);
  107. }
  108. public function __invoke(){
  109. return $this->query;
  110. }
  111. public function execute(){
  112. if($this->query){
  113. $this->query->free_result();
  114. $this->_result = false;
  115. $this->query->reset();
  116. $r = $this->query->execute();
  117. $this->sql->commit();
  118. return $r;
  119. }else{
  120. return false;
  121. }
  122. }
  123. public function each_assoc(callable $fn){
  124. if($this->query){
  125. $r = $this->results;
  126. while($row = $r->fetch_assoc()){
  127. $fn($row);
  128. }
  129. }else{
  130. return false;
  131. }
  132. }
  133. public function each_num(callable $fn){
  134. if($this->query){
  135. $r = $this->results;
  136. while($row = $r->fetch_num()){
  137. $fn($row);
  138. }
  139. }else{
  140. return false;
  141. }
  142. }
  143. public function __get($name){
  144. switch($name){
  145. /**
  146. * Returns the mysqli::results object for the
  147. * query
  148. *
  149. * @property results
  150. * @type {mysqli::results}
  151. * @public
  152. */
  153. case 'results':
  154. if(!$this->_result && $this->query){
  155. $this->execute();
  156. $this->_result = $this->query->get_result();
  157. $this->query->close();
  158. }
  159. return $this->_result;
  160. break;
  161. /**
  162. * Returns an associative array of the query resulsts
  163. *
  164. * @property assoc_results
  165. * @type {Array}
  166. * @public
  167. */
  168. /**
  169. * Returns an associative array of the query resulsts
  170. *
  171. * @property resulsts_assoc
  172. * @type {Array}
  173. * @public
  174. */
  175. case 'assoc_results':case 'results_assoc':
  176. if($this->query){
  177. $a = [];
  178. $r = $this->results;
  179. while($row = $r->fetch_assoc()){
  180. array_push($a,$row);
  181. }
  182. return $a;
  183. }else{
  184. return false;
  185. }
  186. break;
  187. /**
  188. * Returns a numbered array of the query results
  189. *
  190. * @property num_results
  191. * @type {Array}
  192. * @public
  193. */
  194. /**
  195. * Returns a numbered array of the query results
  196. *
  197. * @property resulsts_num
  198. * @type {Array}
  199. * @public
  200. */
  201. case 'num_results':case 'results_num':
  202. if($this->query){
  203. $a = [];
  204. $r = $this->results;
  205. while($row = $r->fetch_num()){
  206. array_push($a,$row);
  207. }
  208. return $a;
  209. }else{
  210. return false;
  211. }
  212. break;
  213. case 'assoc_result':case 'result_assoc':
  214. if($this->query){
  215. $r = $this->results;
  216. return $r?$r->fetch_assoc():false;
  217. }else{
  218. return false;
  219. }
  220. break;
  221. case 'num_result':case 'result_num':
  222. if($this->query){
  223. $r = $this->results;
  224. return $r?$r->fetch_num():false;
  225. }else{
  226. return false;
  227. }
  228. break;
  229. case 'insert_id':
  230. return $this->sql->insert_id;
  231. break;
  232. case 'affected_rows':
  233. return $this->query->affected_rows;
  234. break;
  235. }
  236. }
  237. }
  238. register_shutdown_function(function(){
  239. SQL::shutdown();
  240. });
  241. ?>