├── LICENSE ├── README ├── mysqldatabase.php └── mysqlresultset.php /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011, Micah Carrick 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this list 8 | of conditions and the following disclaimer. Redistributions in binary form must 9 | reproduce the above copyright notice, this list of conditions and the following 10 | disclaimer in the documentation and/or other materials provided with the 11 | distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | PHP MySQL Database Class 2 | ======================== 3 | 4 | Copyright (c) 2011 Micah Carrick 5 | All Rights Reserved. 6 | 7 | PHP MySQL Database Class is singleton pattern object which serves as a MySQL 8 | database wrapper and an iterator result set object. This project was developed 9 | as a follow up to my older, PHP4 database class from 2004. 10 | 11 | 12 | Basic Usage 13 | ----------- 14 | For a more detailed explanation, consult the phpDocumentor docstrings within 15 | the source code or visit http://www.micahcarrick.com/php5-mysql-database-class.html 16 | 17 | Here are some simple examples: 18 | 19 | // get the database singleton instance 20 | $db = MySqlDatabase::getInstance(); 21 | 22 | // connect 23 | try { 24 | $db->connect('localhost', 'username', 'password', 'database_name'); 25 | } 26 | catch (Exception $e) { 27 | die($e->getMessage()); 28 | } 29 | 30 | // iterate a resultset 31 | foreach ($db->iterate("SELECT foo FROM bar LIMIT 10") as $row) { 32 | echo $row->foo; 33 | } 34 | 35 | // get just one row 36 | $count = $db->fetchOne("SELECT COUNT(*) FROM foo"); 37 | 38 | // import from a file (use with caution!) 39 | $num = $db->importSqlFile('test-data.sql'); 40 | echo "Imported $num statements.
"; 41 | -------------------------------------------------------------------------------- /mysqldatabase.php: -------------------------------------------------------------------------------- 1 | Getting Started 18 | * 19 | * $db = MySqlDatabase::getInstance(); 20 | * 21 | * try { 22 | * $db->connect('localhost', 'user', 'password', 'database_name'); 23 | * } 24 | * catch (Exception $e) { 25 | * die($e->getMessage()); 26 | * } 27 | * 28 | * 29 | * @package mysql-database 30 | * @author Micah Carrick 31 | * @copyright (c) 2010 - Micah Carrick 32 | * @version 2.0 33 | * @license BSD 34 | */ 35 | class MySqlDatabase 36 | { 37 | /** 38 | * The MySQL link identifier created by {@link connect()} 39 | * 40 | * @var resource 41 | */ 42 | public $link; 43 | 44 | /** 45 | * @var string 46 | */ 47 | private $conn_str; 48 | 49 | /** 50 | * @var MySqlDatabase 51 | */ 52 | private static $instance; 53 | 54 | const MYSQL_DATE_FORMAT = 'Y-m-d'; 55 | const MYSQL_TIME_FORMAT = 'H:i:s'; 56 | const MYSQL_DATETIME_FORMAT = 'Y-m-d H:i:s'; 57 | 58 | const INSERT_GET_AUTO_INCREMENT_ID = 1; 59 | const INSERT_GET_AFFECTED_ROWS = 2; 60 | 61 | /** 62 | * Constructor 63 | * 64 | * Private constructor as part of the singleton pattern implementation. 65 | */ 66 | private function __construct() {} 67 | 68 | /** 69 | * Connect 70 | * 71 | * Establish a connection to a MySQL database. Returns the MySQL link 72 | * link identifier or throws an exception if there is an error. 73 | * 74 | * 75 | * // get an instance of the Database singleton 76 | * $db = MySqlDatabase::getInstance(); 77 | * 78 | * // connect to a MySQL database (use your own login information) 79 | * try { 80 | * $db->connect('localhost', 'user', 'password', 'database_name'); 81 | * } 82 | * catch (Exception $e) { 83 | * die($e->getMessage()); 84 | * } 85 | * 86 | * 87 | * @param string 88 | * @param string 89 | * @param string 90 | * @param string 91 | * @param boolean 92 | * @return resource 93 | */ 94 | public function connect($host, $user, $password, $database=false, $persistant=false) 95 | { 96 | if ($persistant) { 97 | $this->link = @mysql_pconnect($host, $user, $password); 98 | } else { 99 | $this->link = @mysql_connect($host, $user, $password); 100 | } 101 | 102 | if (!$this->link) 103 | { 104 | throw new Exception('Unable to establish database connection: ' 105 | .mysql_error()); 106 | } 107 | 108 | if ($database) $this->useDatabase($database); 109 | 110 | $version = mysql_get_server_info(); 111 | $this->conn_str = "'$database' on '$user@$host' (MySQL $version)"; 112 | 113 | return $this->link; 114 | } 115 | 116 | /** 117 | * Delete 118 | * 119 | * Executes the DELETE statement specified in the query and returns the 120 | * value from either the PHP {@link mysql_affected_rows()} function. Throws 121 | * and exception if there is a MySQL error in the query. 122 | * 123 | * Note: With MySQL versions prior to 4.1.2, the affected rows on DELETE 124 | * statements with no WHERE clause is 0. See {@link mysql_affected_rows()} 125 | * for more information. 126 | * 127 | * @param string 128 | * @return integer 129 | */ 130 | public function delete($query) 131 | { 132 | return $this->updateOrDelete($query); 133 | } 134 | 135 | /** 136 | * Get Connection String 137 | * 138 | * Gets a string representing the connection. 139 | * 140 | * 141 | * echo $db->getConnectionString(); 142 | * // example output: 'test_database' on 'web_user@localhost' (MySQL 5.1.47) 143 | * 144 | * 145 | * @return string 146 | */ 147 | public function getConnectionString() 148 | { 149 | return $this->conn_str; 150 | } 151 | 152 | /** 153 | * Get Instance 154 | * 155 | * Gets the singleton instance for this object. This method should be called 156 | * statically in order to use the Database object: 157 | * 158 | * 159 | * $db = MySqlDatabase::getInstance(); 160 | * 161 | * 162 | * @return MySqlDatabase 163 | */ 164 | public static function getInstance() 165 | { 166 | if (!isset(self::$instance)) 167 | { 168 | self::$instance = new MySqlDatabase(); 169 | } 170 | 171 | return self::$instance; 172 | } 173 | 174 | /** 175 | * Fetch One From Each Row 176 | * 177 | * Convenience method to get a single value from every row in a given 178 | * query. This is usefull in situations where you know that the result will 179 | * only have only one column of data and you need that all in a simple 180 | * array. 181 | * 182 | * 183 | * 184 | * $query = "SELECT name FROM users"; 185 | * $names = $db->fetchOneFromEachRow($query); 186 | * echo 'Users: ' . implode(', ', $names); 187 | * 188 | * 189 | * @param string 190 | * @return array 191 | */ 192 | public function fetchOneFromEachRow($query) 193 | { 194 | $rval = array(); 195 | 196 | foreach ($this->iterate($query, MySqlResultSet::DATA_NUMERIC_ARRAY) as $row) { 197 | $rval[] = $row[0]; 198 | } 199 | 200 | return $rval; 201 | } 202 | 203 | /** 204 | * Fetch One Row 205 | * 206 | * Convenience method to get a single row from a given query. This is 207 | * usefull in situations where you know that the result will only contain 208 | * one record and therefore do not need to iterate over it. 209 | * 210 | * You can 211 | * optionally specify the type of data to be returned (object or array) 212 | * using one of the MySqlResultSet Data Constants. The default is 213 | * {@link MySqlResultSet::DATA_OBJECT}. 214 | * 215 | * 216 | * // get one row of data 217 | * $query = "SELECT first, last FROM users WHERE user_id = 24 LIMIT 1"; 218 | * $row = $db->fetchOneRow($query); 219 | * echo $row->foo; 220 | * echo $row->bar; 221 | * 222 | * 223 | * @param string 224 | * @param integer 225 | * @return mixed 226 | */ 227 | public function fetchOneRow($query, $data_type=MySqlResultSet::DATA_OBJECT) 228 | { 229 | $result = new MySqlResultSet($query, $data_type, $this->link); 230 | $result->rewind(); 231 | $row = $result->current(); 232 | 233 | return $row; 234 | } 235 | 236 | /** 237 | * Fetch One 238 | * 239 | * Convenience method to get a single value from a single row. Returns the 240 | * value if the query returned a record, false if there were no results, or 241 | * throws an exception if there was an error with the query. 242 | * 243 | * 244 | * // get the number of records in the 'users' table 245 | * $count = $db->fetchOne("SELECT COUNT(*) FROM users"); 246 | * 247 | * 248 | * @param string 249 | * @return mixed 250 | */ 251 | public function fetchOne($query) 252 | { 253 | $result = new MySqlResultSet($query, MySqlResultSet::DATA_NUMERIC_ARRAY, 254 | $this->link); 255 | $result->rewind(); 256 | $row = $result->current(); 257 | 258 | if (!$row) return false; 259 | else return $row[0]; 260 | } 261 | 262 | /** 263 | * Import SQL File 264 | * 265 | * Runs the queries defined in an SQL script file. The double-hyphen style 266 | * comments must have a single space after the hyphens. Hash style comments 267 | * and C-style comments are also supported. 268 | * 269 | * An optional user callback function can be specified to get information 270 | * about each MySQL statement. The user callback function takes 3 271 | * parameters: the line number as an integer, the query as a string, and the 272 | * result of the query as a boolean. 273 | * 274 | * 275 | * function import_sql_callback($line_number, $sql_query, $result) 276 | * { 277 | * echo "Line $line_number: $sql_query "; 278 | * if ($result) echo "(OK)
"; 279 | * else echo "(FAIL)
"; 280 | * } 281 | *
282 | * 283 | * You can optionally specify whether or not to abort importing statements 284 | * when an SQL error occurs (defaults to 'true') in which case an exception 285 | * will be thrown for any MySQL error. 286 | * 287 | * Returns the number of queries executed from the script or throws an 288 | * exception if there is an error. 289 | * 290 | * 291 | * // no callback, throw exception on MySQL errors 292 | * $number = $db->importSqlFile('queries.sql'); 293 | * 294 | * // callback for each query, skip queries with MySQL errors 295 | * $number = $db->importSqlFile('queries.sql', 'import_sql_callback', false); 296 | * 297 | * 298 | * TODO: Ensure this works with huge files. Might need to use fopen() 299 | * 300 | * @param string 301 | * @param string 302 | * @param boolean 303 | * @return integer 304 | */ 305 | public function importSqlFile($filename, $callback=false, $abort_on_error=true) 306 | { 307 | if ($callback && !is_callable($callback)) { 308 | throw new Exception("Invalid callback function."); 309 | } 310 | 311 | $lines = $this->loadFile($filename); 312 | 313 | $num_queries = 0; 314 | $sql_line = 0; 315 | $sql = ''; 316 | $in_comment = false; 317 | 318 | foreach ($lines as $num => $line) { 319 | 320 | $line = trim($line); 321 | $num++; 322 | if (empty($sql)) $sql_line = $num; 323 | 324 | // ignore comments 325 | 326 | if ($in_comment) { 327 | $comment = strpos($line, '*/'); 328 | 329 | if ($comment !== false) { 330 | $in_comment = false; 331 | $line = substr($line, $comment+2); 332 | } else { 333 | continue; 334 | } 335 | 336 | } else { 337 | 338 | $comment = strpos($line, '/*'); 339 | 340 | if ($comment !== false) { 341 | 342 | if (strpos($line, '*/') === false) { 343 | $in_comment = true; 344 | } 345 | 346 | $line = substr($line, 0, $comment); 347 | 348 | } else { 349 | 350 | // single line comments 351 | 352 | foreach (array('-- ', '#') as $chars) { 353 | $comment = strpos($line, $chars); 354 | 355 | if ($comment !== false) { 356 | $line = substr($line, 0, $comment); 357 | } 358 | } 359 | } 360 | } 361 | 362 | // check if the statement is ready to be queried 363 | 364 | $end = strpos($line, ';'); 365 | 366 | if ($end === false) { 367 | $sql .= $line; 368 | } else { 369 | $sql .= substr($line, 0, $end); 370 | $result = $this->quickQuery($sql); 371 | $num_queries++; 372 | 373 | if (!$result && $abort_on_error) { 374 | $file = basename($filename); 375 | $error = mysql_error($this->link); 376 | throw new Exception("Error in $file on line $sql_line: $error"); 377 | } 378 | 379 | if ($callback) { 380 | call_user_func($callback, $sql_line, $sql, $result); 381 | } 382 | 383 | $sql = ''; // clear for next statement 384 | 385 | } 386 | } 387 | 388 | return $num_queries; 389 | } 390 | 391 | /** 392 | * Is Connected 393 | * 394 | * Determines if there is a connection open to the database. 395 | * 396 | * @return boolean 397 | */ 398 | public function isConnected() 399 | { 400 | if (!empty($this->link)) { 401 | return @mysql_ping($this->link); 402 | } else { 403 | return false; 404 | } 405 | } 406 | 407 | // insertPhpArray 408 | // insertSqlArray 409 | // sqlval() 410 | 411 | /** 412 | * Insert 413 | * 414 | * Executes the INSERT statement specified in the query and returns the 415 | * value from either the PHP {@link mysql_insert_id()} function or the 416 | * php {@link mysql_affected_rows()} function depending on the value of the 417 | * $return_type parameter. 418 | * 419 | * 420 | * $db = MySqlDatabase::getInstance(); 421 | * $query = "INSERT INTO foobar (col1, col2) VALUES (1, 2), (2, 3)"; 422 | * $rows = $db->insert($query, MySqlDatabase::INSERT_GET_AFFECTED_ROWS); 423 | * echo $rows; // output: 2 424 | * 425 | * 426 | * 427 | * @param string 428 | * @param integer 429 | * @return integer 430 | */ 431 | public function insert($query, $r_type=MySqlDatabase::INSERT_GET_AUTO_INCREMENT_ID) 432 | { 433 | $r = $this->query($query); 434 | 435 | if ($r_type == MySqlDatabase::INSERT_GET_AFFECTED_ROWS) { 436 | return @mysql_affected_rows($this->link); 437 | } else { 438 | return @mysql_insert_id($this->link); 439 | } 440 | } 441 | 442 | /** 443 | * DO NOT USE 444 | * 445 | * This was never finished... I don't think. The goal was to take a table 446 | * name, an array of column names, and an array of values and generate a 447 | * multiple record insert. You should not use this, but, you could help 448 | * out and finish or rewrite this method. 449 | * 450 | * 451 | * @param deprecated 452 | */ 453 | public function smartInsert($table, $columns, $values) 454 | { 455 | if (empty($table) || !is_string($table)) { 456 | throw new Exception('The $table parameter must be specified as a string.'); 457 | } 458 | 459 | $table_sql = '`' . @mysql_real_escape_string($table) . '`'; 460 | $query = "INSERT INTO $table_sql "; 461 | 462 | // columns 463 | if (is_string($columns)) { 464 | $columns = explode(',', $columns); 465 | } 466 | 467 | if (is_array($columns)) { 468 | foreach ($columns as &$col) { 469 | if (!is_string($col)) { 470 | throw new Exception('The $columns parameter must be a string or an array of strings'); 471 | } 472 | $col = @mysql_real_escape_string($col); 473 | } 474 | $column_sql = implode(',', $columns); 475 | $column_count = count($columns); 476 | } else { 477 | throw new Exception('The $columns parameter must be a string or an array of strings.'); 478 | } 479 | 480 | try { 481 | $column_info = array(); 482 | 483 | foreach ($this->iterate("SHOW COLUMNS FROM $table_sql") as $row) { 484 | $column_info[] = $row; 485 | } 486 | } 487 | catch (Exception $e) { 488 | throw new Exception("Could not get column information for table $table_sql."); 489 | } 490 | 491 | $query .= "($column_sql) "; 492 | 493 | // values 494 | 495 | if (is_array($values)) { 496 | for ($i=0; $i < count($values); $i++) { 497 | $info = $column_info[$i]; 498 | $value = $values[i]; 499 | 500 | // Where the heck did I leave off? 501 | } 502 | } else { 503 | // TODO: if only 1 column, then this will work 504 | 505 | throw new Exception('The $values parameter must be a string or an array.'); 506 | } 507 | 508 | if (isset($column_count) && $column_count <> $value_count) { 509 | throw new Exception("Column count ($column_count) does not match values count ($value_count)."); 510 | } 511 | 512 | $query .= "VALUES ($value_sql) "; 513 | 514 | echo $query; 515 | 516 | } 517 | 518 | /** 519 | * Iterate Result Set 520 | * 521 | * Returns a {@link MySQL_ResultSet} iteratable object for a query. The $type 522 | * parameter indicates the data being iterated should be an object, 523 | * a numerically indexed array, an associative array, or an array with 524 | * both numeric and associative indexes. Defaults to objects. 525 | * 526 | * 527 | * $sql_query = "SELECT col1, col2 FROM table"; 528 | * 529 | * // iterate as objects 530 | * foreach ($db->iterate("SELECT col1, col2 FROM table") as $row) { 531 | * echo $row->col1 . '
'; 532 | * echo $row->col2 . '
'; 533 | * } 534 | * 535 | * // iterate as both associative and numerically indexed array 536 | * foreach ($db->iterate($sql_query, MySQL_Db::DATA_ARRAY) as $row) { 537 | * echo $row[0] . '
'; 538 | * echo $row['col1'] . '
'; 539 | * } 540 | *
541 | * 542 | * @param string 543 | * @param integer 544 | * @return boolean 545 | */ 546 | public function iterate($sql, $data_type=MySqlResultSet::DATA_OBJECT) 547 | { 548 | return new MySqlResultSet($sql, $data_type, $this->link); 549 | } 550 | 551 | /** 552 | * Load File 553 | * 554 | * Loads the specified filename into an array of lines. Throws an exception 555 | * if there is an error. 556 | * 557 | * @param string 558 | * @return boolean 559 | */ 560 | private function loadFile($filename) 561 | { 562 | if (!file_exists($filename)) { 563 | throw new Exception("File does not exist: $filename"); 564 | } 565 | 566 | $file = @file($filename, FILE_IGNORE_NEW_LINES); 567 | 568 | if (!$file) { 569 | throw new Exception("Could not open $filename"); 570 | } 571 | 572 | return $file; 573 | } 574 | 575 | public function query($query) 576 | { 577 | $r = @mysql_query($query, $this->link); 578 | 579 | if (!$r) { 580 | throw new Exception("Query Error: " . mysql_error()); 581 | } 582 | 583 | return $r; 584 | } 585 | 586 | /** 587 | * Quick Query 588 | * 589 | * Executes a MySQL query and returns a boolean value indicating success 590 | * or failure. This method will close any resources opened from 591 | * SELECT, SHOW, DESCRIBE, or EXPLAIN statements and would not be very 592 | * usefull for those types of queries. This method is used internally for 593 | * importing SQL scripts. 594 | * 595 | * @param string 596 | * @return boolean 597 | */ 598 | public function quickQuery($query) 599 | { 600 | $r = @mysql_query($query, $this->link); 601 | 602 | if (!$r) return false; 603 | if (is_resource($r)) mysql_free_result($r); 604 | 605 | return true; 606 | } 607 | 608 | /** 609 | * Update 610 | * 611 | * Executes the UPDATE statement specified in the query and returns the 612 | * value from either the PHP {@link mysql_affected_rows()} function. Throws 613 | * and exception if there is a MySQL error in the query. 614 | * 615 | * Note: The number of rows affected include only those in which the new 616 | * value was not the same as the old value. See {@link mysql_affected_rows()} 617 | * for more information. 618 | * 619 | * @param string 620 | * @return integer 621 | */ 622 | public function update($query) 623 | { 624 | return $this->updateOrDelete($query); 625 | } 626 | 627 | private function updateOrDelete($query) 628 | { 629 | $r = $this->query($query); 630 | return @mysql_affected_rows($this->link); 631 | } 632 | 633 | /** 634 | * Use Database 635 | * 636 | * Selects the database to use. Throws an exception if there is an error 637 | * using the specified database. 638 | * 639 | * @param string 640 | * @return integer 641 | */ 642 | public function useDatabase($database) 643 | { 644 | if (!@mysql_select_db($database, $this->link)) 645 | { 646 | throw new Exception('Unable to select database: ' . mysql_error($this->link)); 647 | } 648 | } 649 | } 650 | 651 | 652 | 653 | ?> 654 | -------------------------------------------------------------------------------- /mysqlresultset.php: -------------------------------------------------------------------------------- 1 | 22 | * $db = MySqlDatabase::getInstance(); 23 | * $db->connect('localhost', 'user', 'password', 'database_name'); 24 | * 25 | * // $db->iterate() returns a new MySqlResultSet instance 26 | * foreach ($db->iterate("SELECT * FROM users LIMIT 100") as $row) { 27 | * print_r($row); 28 | * } 29 | * 30 | * 31 | * @package mysql-database 32 | * @author Micah Carrick 33 | * @copyright (c) 2010 - Micah Carrick 34 | * @version 2.0 35 | * @license BSD 36 | */ 37 | class MySqlResultSet implements Iterator 38 | { 39 | private $query; 40 | private $result; 41 | private $index = 0; 42 | private $num_rows = 0; 43 | private $row = false; 44 | private $type; 45 | 46 | /** 47 | * Object Data 48 | * 49 | * The data will be fetched as an object, where the columns of the table 50 | * are property naems of the object. See 51 | * {@link mysql_fetch_object()}. 52 | */ 53 | const DATA_OBJECT = 1; 54 | 55 | /** 56 | * Numeric Array Data 57 | * 58 | * The data will be fetched as a numerically indexed array. See 59 | * {@link mysql_fetch_row()}. 60 | */ 61 | const DATA_NUMERIC_ARRAY = 2; 62 | 63 | /** 64 | * Keyed Array Data 65 | * 66 | * The data will be fetched as an associative array. See 67 | * {@link mysql_fetch_assoc()}. 68 | */ 69 | const DATA_ASSOCIATIVE_ARRAY = 3; 70 | 71 | /** 72 | * Array Data 73 | * 74 | * The data will be fetched as both an associative and indexed array. See 75 | * {@link mysql_fetch_array()}. 76 | */ 77 | const DATA_ARRAY = 4; 78 | 79 | /** 80 | * Constructor 81 | * 82 | * The constructor requires an SQL query which should be a query that 83 | * returns a MySQL result resource such as a SELECT query. If the query 84 | * fails or does not return a result resource, the constructor will throw 85 | * an exception. 86 | * 87 | * The optional $data_type parameter specifies how to fetch the data. One 88 | * of the data constants can be specified or the default 89 | * {@link MySqlResultSet::DATA_OBJECT} will be used. 90 | * 91 | * @param string 92 | * @param integer 93 | */ 94 | public function __construct($query, $data_type=MySqlResultSet::DATA_OBJECT, 95 | $link=false) 96 | { 97 | if ($link) $this->result = @mysql_query($query, $link); 98 | else $this->result = @mysql_query($query); 99 | 100 | if (!$this->result) { 101 | throw new Exception(mysql_error()); 102 | } 103 | 104 | if (!is_resource($this->result) 105 | || get_resource_type($this->result) != 'mysql result') { 106 | throw new Exception("Query does not return an mysql result resource."); 107 | } 108 | 109 | $this->query = $query; 110 | $this->num_rows = mysql_num_rows($this->result); 111 | $this->type = $data_type; 112 | } 113 | 114 | /** 115 | * Destructor 116 | * 117 | * The destructor will free the MySQL result resource if it is valid. 118 | */ 119 | public function __destruct() 120 | { 121 | if (is_resource($this->result) 122 | && get_resource_type($this->result) == 'mysql result') { 123 | mysql_free_result($this->result); 124 | } 125 | } 126 | 127 | private function fetch() 128 | { 129 | if ($this->num_rows > 0) { 130 | switch ($this->type) { 131 | case MySqlResultSet::DATA_NUMERIC_ARRAY: 132 | $func = 'mysql_fetch_row'; 133 | break; 134 | case MySqlResultSet::DATA_ASSOCIATIVE_ARRAY: 135 | $func = 'mysql_fetch_assoc'; 136 | break; 137 | case MySqlResultSet::DATA_ARRAY: 138 | $func = 'mysql_fetch_array'; 139 | default: 140 | $func = 'mysql_fetch_object'; 141 | break; 142 | } 143 | 144 | $this->row = $func($this->result); 145 | $this->index++; 146 | } 147 | } 148 | 149 | public function getResultResource() 150 | { 151 | return $this->result; 152 | } 153 | 154 | public function isEmpty() 155 | { 156 | if ($this->num_rows == 0) return true; 157 | else return false; 158 | } 159 | 160 | /** 161 | * Rewind 162 | * 163 | * Rewind the Iterator to the first row of data. 164 | */ 165 | public function rewind() 166 | { 167 | if ($this->num_rows > 0) { 168 | mysql_data_seek($this->result, 0); 169 | $this->index = -1; // fetch() will increment to 0 170 | $this->fetch(); 171 | } 172 | } 173 | 174 | /** 175 | * Current Row 176 | * 177 | * Get the current row of data. The type of data is determined by the $type 178 | * parameter passed to the constructor. 179 | * 180 | * @return mixed 181 | */ 182 | function current() 183 | { 184 | return $this->row; 185 | } 186 | 187 | /** 188 | * Key 189 | * 190 | * Get the index for the current row. The index begins at 0 with the first 191 | * row of data. 192 | * 193 | * @return integer 194 | */ 195 | function key() 196 | { 197 | return $this->index; 198 | } 199 | 200 | /** 201 | * Next 202 | * 203 | * Move forward to the next row in the result set. 204 | */ 205 | function next() 206 | { 207 | $this->fetch(); 208 | } 209 | 210 | /** 211 | * Valid 212 | * 213 | * Determines if the current row is valid. 214 | * 215 | * @return boolean 216 | */ 217 | function valid() 218 | { 219 | if ($this->row === false) return false; 220 | else return true; 221 | } 222 | } 223 | ?> 224 | --------------------------------------------------------------------------------