PHP Classes

File: simplesql.class.php5

Recommend this page to a friend!
  Classes of Paul Williamson   Simple SQL PHP 5   simplesql.class.php5   Download  
File: simplesql.class.php5
Role: Class source
Content type: text/plain
Description: main class file
Class: Simple SQL PHP 5
PHP 5 version of a MySQL wrapper and query logger
Author: By
Last change:
Date: 19 years ago
Size: 46,257 bytes
 

Contents

Class file image Download
<?php /** * SimpleSQL - The Simplest Way to Query * Copyright (c) 2004 Paul Williamson <webmaster@protonage.net> * * This class is ment to shortcut common MySQL database access tasks. * FOR PHP 5 ONLY! This class will not work on any versons < PHP5! * Also, This class was designed for users who want to use the new * PHP5 Improved MySQL Extension (mysqli) but do not have MySQL > 4.1. * Mysqli allows you to access the functionality provided by MySQL > 4.1 * Later on in the future, I will add a layer to this class that allows * mysqli functionality. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * @category Database * @package SimpleSQL * @author Paul Williamson <webmaster@protonage.net> * @readme ./docs/README.txt * @example ./docs/EXAMPLES.txt * @standards ./docs/CODING_STANDARDS.txt * @version $Id: simplesql.class.php5,v 2.0 2004/08/08 19:37:45 paul Exp $ */ define ('FETCH_ASSOC', 0); define ('FETCH_NUM', 1); define ('FETCH_OBJECT', 2); class simplesql { /** * Constants; * * VERSION; SimpleSQL Version @const string * LOG_PATH; Path to logs @const string * MAX_SIZE; Max size of log file @const int * DATE_FORMAT; Date Format for Log @const string * @access global */ const VERSION = 'SimpleSQL v2.0.1 PHP5'; const LOG_PATH = '.'; const MAX_SIZE = 2000000; const DATE_FORMAT = 'F jS, Y, H:i:s T'; /** * Database Variables; * * You may hardcode these variables and not have to worry * about providing any arguments when you create a new class * * $fetch_default; How the result is returned @var int * * $host; Database Server @var string * $user; Database Username @var string * $pass; Database Password @var string * $dbname; Database name @var string * $socket; Database Socket @var string * $port; Database Port @var int * * $resultrows; Number of rows from query @var int * $table; Last table used in query @var string * * $connection; Connection link identifier @var resource * $preg_sql_noquote; Regular Expression * pattern for fix_sql() @var string * $preg_sql_quote; Regular Expression * pattern for fix_sql() @var string * $preg_lst_noquote; Regular Expression * pattern for fix_list() @var string * $preg_lst_quote; Regular Expression * pattern for fix_list() @var string * Be careful with backrefs * @access mixed */ public $fetch_default = FETCH_OBJECT; protected $host = 'localhost'; protected $user = 'root'; protected $pass = ''; protected $dbname = 'database'; protected $socket; protected $port = 3306; protected $resultrows = 0; protected $table = ''; private $connection = false; private $preg_sql_noquote = '/^([a-zA-Z0-9\._]+ *= *[^, ]+)((, )|$)(.*)/i'; private $preg_sql_quote = '/^([a-zA-Z0-9\._]+( *= *[\'"`].*?[\'"`])?)((, )|$)(.*)/i'; private $preg_lst_noquote = '/^([a-zA-Z0-9\._]*) *(,|$) *(.*)$/is'; private $preg_lst_quote = '/^{quote}(.*?){quote} *(,|$) *(.*)$/is'; /** * Common Variables; * * $tracklog; Put every event in array @var bool * $showlog; Print log array to screen (debug) @var bool * $logtofile; Log tracks to a data file @var bool * $logfulltofile; Entire log array is @var bool * serilized into file * @access protected */ protected $common = array( 'tracklog' => true, 'showlog' => false, 'logtofile' => true, 'logfulltofile' => true ); /** * Debug Variables; * $session; Session ID for class @var string * $birth; Time the class began @var float * $querytime; Time spent executing queries @var float * $querycount; Number of executed queries @var int * $log; Log of actions & errors @var array * $log; Log of just errors @var array * $result; Result from query @var resource */ protected $session; protected $birth = 0; protected $querytime = 0; protected $querycount = 0; protected $log = array(); protected $error_log = array(); protected $result = array(); /** * Constructor; sets up connection varables and connects * * @param string $db_host Server * @param string $db_user Username * @param string $db_pass Password * @param string $db_name Database Name * @param int $db_port Database Port * @param string $db_socket Database Socket * @author Paul Williamson <webmaster@protonage.net> * @access private * @return void */ function __construct($db_host = NULL, $db_user = NULL, $db_pass = NULL, $db_name = NULL, $db_port = 3306, $db_socket = '') { $this->birth = $this->timenow(); $this->session = md5(round($this->birth, 3)*1000); $this->log=array( 'session' => $this->session, 'date' => date("F jS, Y, H:i:s T"), 'birth' => $this->birth, 'age' => $this->age(), 'mysql' => array() ); $this->set_param($db_host, 'host'); $this->set_param($db_user, 'user'); $this->set_param($db_pass, 'pass'); $this->set_param($db_name, 'dbname'); $this->set_param($db_port, 'port'); $this->set_param($db_socket, 'socket'); try { $this->connect(); } catch (Exception $e) { $this->track('error', '__construct', self::VERSION . " session Id: {$this->log['session']}" . ' could not establish a connection' . ' to server ' . $this->host . ' and' . ' therefore could not be created.' . ' View error log for more details.', $e ); trigger_error(self::VERSION . " session Id: {$this->log['session']} could not" . ' be created! The class will now terminate. Exception:' . ' ' . $e->getmessage(), E_USER_ERROR ); } $this->track('event', '__construct', self::VERSION . " session Id: {$this->log['session']} has been" . " constructed @ {$this->log['date']}" ); } /** * Destruct; destroys connection and reports logs * * @param boolean $re Reconnect * @author Paul Williamson <webmaster@protonage.net> * @access private * @return void */ function __destruct() { $this->kill(); $this->track('event', '__destruct', self::VERSION . " session Id: {$this->log['session']} has been" . ' destructed @ ' . date(self::DATE_FORMAT) . '.' ); $this->log['mysql'] = array_merge($this->log['mysql'], array( 'querycount' => $this->querycount, 'querytime' => $this->querytime ) ); $this->log['age'] = $this->age(); if ($this->common['logtofile']) $this->do_log(); if ($this->common['logfulltofile']) $this->do_fulllog(); if ($this->common['showlog']) $this->printlog(); } /** * Call; Picks up any undeclaired methods * * @param string $m Method called * @author Paul Williamson <webmaster@protonage.net> * @access private * @return void */ function __call($m) { $from = trim($m); $this->track('error', $from, 'Method does not exists!' ); } /** * Get; Get a variable's value * * @param string $var variable * @author Paul Williamson <webmaster@protonage.net> * @access private * @return mixed */ function __get($var) { if (isset($this->common[$var])) { return $this->common[$var]; } else { $this->track('error', '__get', "Variable {$var} does not exists" ); return null; } } /** * Set; Set a variable's value * * @param string $var variable * @param string $val value to be assigned * @author Paul Williamson <webmaster@protonage.net> * @access private * @return void */ function __set($var, $val) { if (isset($this->common[$var])) { $this->common[$var] = $val; } else { $this->track('error', '__set', "Variable {$var} does not exists" ); } } /** * SelectDB; Selects the database * * @param string $db Database to select * @param resouce $conn conection resource * @author Paul Williamson <webmaster@protonage.net> * @access public * @return boolean */ public function selectdb($db, $conn) { if (!@mysql_select_db($db, $conn)) { $this->track('error', 'connect', "Could not select database {$this->dbname}.", mysql_error($this->connection) ); $this->connection = false; return false; } return true; } /** * Connect; connects to a database * * @param boolean $re Reconnect * @author Paul Williamson <webmaster@protonage.net> * @access public * @return boolean */ public function connect($re = false) { $server = "{$this->host}:{$this->port}" . (!$this->socket ? '' : $this->socket); $r = $re ? 'Rec' : 'C'; if (!$this->connection || !$re) { if (($this->connection = @mysql_connect($server, $this->user, $this->pass)) === false) { $this->track('error', 'connect', "Could not open a connection to `{$server}`.", mysql_error() ); throw new Exception(mysql_error($this->connection)); return false; } if (!$this->selectdb($this->dbname, $this->connection)) { throw new Exception('Could not select database: ' . $this->dbname); return false; } } else { if (!mysql_ping($this->connection)) { $this->track('error', 'connect', "Could not reconnect to `{$server}`.", mysql_error($this->connection) ); throw new Exception(mysql_error($this->connection)); return false; } } $this->track('event', 'connect', "{$r}onnected to `{$server}`." ); return true; } /** * Query; Sends query to database * * @param string $query Query String * @author Paul Williamson <webmaster@protonage.net> * @access public * @return resource */ final public function query($query) { $start = $this->timenow(); $result = @mysql_query($query, $this->connection); $querytime = $this->timenow()-$start; $querydeath = $this->age(); if ($result !== false) { $this->track('event', 'query', "Query: {$query}", '', $querydeath ); } else { $this->track('error', 'query', "Query Failed: `{$query}`", mysql_error($this->connection), $querydeath ); throw new Exception(mysql_error($this->connection)); return false; } $this->querytime += $querytime; $this->querycount ++; $data = array(); if (substr(trim(strtoupper($query)), 0, 6) == 'SELECT') { $data = mysql_fetch_array(mysql_query("EXPLAIN {$query}", $this->connection), MYSQL_ASSOC ); $this->resultrows = mysql_num_rows($result); } $type = ''; $rows = 0; $key = ''; $possible_keys = ''; $Extra = ''; $intensity = 1; extract($data); if ($querytime > 0.05) $intensity++; if ($querytime > 0.1) $intensity++; if ($querytime > 1) $intensity++; if ($type == 'ALL') $intensity++; if ($type == 'index') $intensity++; if ($type == 'range') $intensity++; if ($type == 'ref') $intensity++; if ($rows >= 200) $intensity++; if (!empty($possible_keys) && empty($key)) { $intensity++; } if ((strpos($Extra, 'Using filesort') !== false) || (strpos($Extra, 'Using temporary') !== false)) { $intensity++; } $data['query'] = $query; $data['query_time'] = $querytime; $data['query_death'] = $querydeath; $data['query_intensity'] = $intensity; $data['result_rows'] = $this->resultrows; $this->log['mysql'][] = $data; if (isset($Comment)) { $this->track('error', 'query', "Query Warning", $Comment ); throw new Exception($Comment); $result = false; } return $result; } /** * Fetch_Query; Send a query and fetch the results * * @param mixed $query Query that will be sent * @param int $fetch Controls the result datatype * @author Paul Williamson <webmaster@protonage.net> * @access public * @return mixed */ public function fetch_query($query, $fetch = NULL) { $this->set_param($fetch, 'fetch_default'); $return = false; try { if (($result = $this->query($query)) !== false) { while($row = $this->fetch($result, $fetch)) { $return[] = $row; } $this->result = $return; } } catch (Exception $e) { $this->track('error', 'fetch_query', $e->getmessage() ); } $this->track('event', 'fetch_query', 'Successful Call (Query: `' . $query . '`)' ); return $return; } /** * Fetch_Col; Fetch (a) Coloumn(s) of data from the database * * @param mixed $field Field(s) that will be used * @param mixed $table Table that will be used * @param int $fetch Controls the result datatype * @param string $order field to order by (append DESC if needed) * @param mixed $limit Limit the result to this number * @author Paul Williamson <webmaster@protonage.net> * @access public * @return mixed */ public function fetch_col($field = NULL, $table = NULL, $fetch = NULL, $order = NULL, $limit = NULL) { $this->set_param($table, 'table'); $this->set_param($fetch, 'fetch_default'); $sql = array(); $return = false; if (empty($field)) { unset($field); $field = $this->fetch( $this->query("SHOW COLUMNS FROM {$table}"), FETCH_NUM ); $field = $field[0]; } for ($z = 0; $z < 2; $z++) { $a = $z ? 'table' : 'field'; $sql[$a] = is_array($$a) ? implode(", ", $$a) : $$a; } $sql['order'] = $order; $sql['limit'] = $limit; try { $query = $this->fix_sql($sql); if (($result = $this->query($query)) !== false) { while($row = $this->fetch($result, $fetch)) { $return[] = $row; } $this->result = $return; } } catch (Exception $e) { $this->track('error', 'fetch_col', $e->getmessage() ); } $this->track('event', 'fetch_col', 'Successful Call (Query: `' . $query . '`)' ); return $return; } /** * Fetch_Row; Fetch (a) Row(s) of data from the database * * This function is nearly identical to Fetch Column but instead * this function will fetch all fields in the table instead of * the ones listed in the arguments. Also this function has all * optional arguments. * * @param mixed $field Field(s) that will be used * @param mixed $table Table that will be used * @param int $fetch Controls the result datatype (array or object) * @param string $order field to order by (append DESC if needed) * @param mixed $limit Limit the result to this number * @author Paul Williamson <webmaster@protonage.net> * @access public * @return mixed */ public function fetch_row($field = NULL, $table = NULL, $fetch = NULL, $order = NULL, $limit = NULL) { $this->set_param($table, 'table'); $this->set_param($fetch, 'fetch_default'); $sql = array(); $return = false; for ($z = 0; $z < 2; $z++) { $a = $z ? 'table' : 'field'; $sql[$a] = is_array($$a) ? implode(", ", $$a) : $$a; } $sql['order'] = $order; $sql['limit'] = $limit; try { $query = $this->fix_sql($sql, 'ALL'); if (($result = $this->query($query)) !== false) { while($row = $this->fetch($result, $fetch)) { $return[] = $row; } $this->result = $return; } } catch (Exception $e) { $this->track('error', 'fetch_row', $e->getmessage() ); } $this->track('event', 'fetch_row', 'Successful Call (Query: `' . $query . '`)' ); return $return; } /** * Fetch_Search; Fetch data bassed on a search pattern * * This function will pass a regular expression string ($find) * to the fix_sql private function. * * @param string $find The varable that will be found in the DB (regexp) * @param mixed $field Field(s) that will be used * @param mixed $table Table that will be used * @param int $fetch Controls the result datatype (array or object) * @param string $order field to order by (append DESC if needed) * @param mixed $limit Limit the result to this number * @author Paul Williamson <webmaster@protonage.net> * @access public * @return mixed */ public function fetch_search($find, $field = NULL, $table = NULL, $fetch = NULL, $order = NULL, $limit = NULL) { $this->set_param($table, 'table'); $this->set_param($fetch, 'fetch_default'); $sql = array(); $return = false; if (empty($field)) { unset($field); $field = $this->fetch( $this->query("SHOW COLUMNS FROM {$table}"), FETCH_NUM ); $field = $field[0]; } for ($z = 0; $z < 2; $z++) { $a = $z ? 'table' : 'field'; $sql[$a] = is_array($$a) ? implode(", ", $$a) : $$a; } $sql['search'] = addcslashes($find, '\''); $sql['order'] = $order; $sql['limit'] = $limit; try { $query = $this->fix_sql($sql, 'ALL'); if (($result = $this->query($query)) !== false) { while($row = $this->fetch($result, $fetch)) { $return[] = $row; } $this->result = $return; } } catch (Exception $e) { $this->track('error', 'fetch_search', $e->getmessage() ); } $this->track('event', 'fetch_search', 'Successful Call (Query: `' . $query . '`)' ); return $return; } /** * Insert; Insert data into a table * * @param mixed $fields Field(s) that will inserted data * @param mixed $values Value(s) that will be inserted * @param string $table Table that will be used * @author Paul Williamson <webmaster@protonage.net> * @access public * @return boolean */ public function insert($fields, $values, $table = NULL) { $this->set_param($table, 'table'); $sql = array(); try { for ($i = 0; $i < 2; $i++) { $a = $i ? 'fields' : 'values'; ${substr($a, 0, 5)} = !is_array($$a) ? $this->fix_list($$a) : $$a; } } catch (Exception $e) { $this->track('error', 'insert', $e->getmessage() ); return false; } if (count($field) != count($value)) { $this->track('error', 'insert', 'Fields and Values do not match in array size' ); return false; } unset($fields); foreach ($field as $f) { if (!$this->field_exists($f, $table)) { $this->track('error', 'insert', "Field: {$f} does not exists in Table: {$table}" ); return false; } $fields .= "{$f}, "; } $sql['insert'] = $table; $sql['field'] = $this->list_trim($fields); $sql['value'] = $value; try { $query = $this->fix_sql($sql); $this->query($query); } catch (Exception $e) { $this->track('error', 'insert', $e->getmessage() ); return false; } $this->track('event', 'insert', 'Successful Call (Query: `' . $query . '`)' ); return true; } /** * Delete; Delete data from a table * * Call this function with limit argument set to -1 * to truncat the table. * * @param mixed $wfield Row that will be deleted * @param boolean $pass A verification array, set it to true * if you are sure you do not want to add a limit to a no-where-clause * DELETE query * @param string $table Table that will be used * @param mixed $limit Limit the result to this number * @author Paul Williamson <webmaster@protonage.net> * @access public * @return boolean */ public function delete($wfield = NULL, $pass = false, $table = NULL, $limit = NULL) { $this->set_param($table, 'table'); $sql = array(); if (!$pass && is_null($wfield)) { $this->track('error', 'delete', 'Function refused to execute query because ' . 'table ' . $table . ' would have been truncated. ' . 'To override this error message, set the second ' . 'argument ($pass) to true.' ); return false; } $sql['delete'] = $table; $sql['field'] = $wfield; $sql['limit'] = $limit; try { $query = $this->fix_sql($sql); $this->query($query); } catch (Exception $e) { $this->track('error', 'delete', $e->getmessage() ); return false; } $this->track('event', 'delete', 'Successful Call (Query: `' . $query . '`)' ); return true; } /** * Update; Update data in a table * * @param mixed $fields Field(s) that will be changed * @param mixed $values Value(s) that will be assigned * @param string $wfields Where fields clause * @param string $table Table that will be used * @param mixed $limit Limit the result to this number * @author Paul Williamson <webmaster@protonage.net> * @access public * @return boolean */ public function update($fields, $values, $wfields = NULL, $table = NULL, $limit = NULL) { $this->set_param($table, 'table'); $sql = array(); try { for ($i = 0; $i < 2; $i++) { $a = $i ? 'fields' : 'values'; ${substr($a, 0, 5)} = !is_array($$a) ? $this->fix_list($$a) : $$a; } } catch (Exception $e) { $this->track('error', 'update', $e->getmessage() ); return false; } if (count($field) != count($value)) { $this->track('error', 'update', 'Fields and Values do not match in array size' ); return false; } unset($fields); $num = count($field); for ($i = 0; $i < $num; $i++) { $f = $field[$i]; $v = $value[$i]; if (!$this->field_exists($f, $table)) { $this->track('error', 'update', "Field: {$f} does not exists in Table: {$table}" ); return false; } $fields .= "{$f}, "; $set .= "`{$f}` = '" . addcslashes($v, '\'') . "', "; } $sql['update'] = $table; $sql['field'] = $wfields; $sql['set'] = $this->list_trim($set); $sql['limit'] = $limit; try { $query = $this->fix_sql($sql); $this->query($query); } catch (Exception $e) { $this->track('error', 'update', $e->getmessage() ); return false; } $this->track('event', 'update', 'Successful Call (Query: `' . $query . '`)' ); return true; } /** * Get_LastQuery; return string of the last executed query * * @author Paul Williamson <webmaster@protonage.net> * @access public * @return string */ public function get_lastquery() { $num = count($this->log['mysql']) - 1; return $this->log['mysql'][$num]['query']; } /** * Get_Result; return result from last SELECT query * * @author Paul Williamson <webmaster@protonage.net> * @access public * @return mixed */ public function get_result() { return $this->result; } /** * Get_Rows; return num rows from last SELECT query * * @author Paul Williamson <webmaster@protonage.net> * @access public * @return int */ public function get_rows() { return $this->resultrows; } /** * Get_Log; return result from last SELECT query * * @param string $key If provided, function will return array of * only the key given. track, mysql, session, etc.. * @author Paul Williamson <webmaster@protonage.net> * @access public * @return array */ public function get_log($key = NULL) { return is_null($key) ? $this->log : $this->log[$key]; } /** * Get_Error; Return the last error (default) or if the first * argument set to true then it will return the full error array * * @param boolean $full Return the full array (default false) * @author Paul Williamson <webmaster@protonage.net> * @access public * @return mixed */ public function get_error($full = false) { return $full ? $this->error_log : end($this->error_log); } /** * Debug; * * Not quite finished with this function. I plan to * make this function return a nice HTML layed out page * of all the logs, stored in raw file, and optomization solutions. * * @author Paul Williamson <webmaster@protonage.net> * @access public * @return string */ public function debug() { //incomplete } /** * Field_Exists; See if field exists in givin table * * @param string $field Field to be found * @param string $table Table that will be searched * @author Paul Williamson <webmaster@protonage.net> * @access public * @return boolean */ public function field_exists($field, $table = NULL) { $this->set_param($table, 'table'); $exists = false; if (is_array($field) || is_array($table)) { $this->track('error', 'field_exists', 'Function does not accept arrays' ); return $exists; } try { $result = mysql_query('SHOW COLUMNS FROM ' . $table, $this->connection); while($row = $this->fetch($result, FETCH_ASSOC)) { if (strtolower($row['Field']) == strtolower($field)) { $exists = true; break; } } } catch(Exception $e) { $this->track('error', 'field_exists', $e->getmessage() ); return $exists; } return $exists; } /** * Track; Build log array * * @param string $type Type of entry * @param string $from Function orgin * @param string $msg Message * @param string $error Server error message * @author Paul Williamson <webmaster@protonage.net> * @access private * @return void */ private function track($type, $from, $msg, $error = '', $age = '') { if (!empty($error)) $this->error_log[] = $error; if (!$this->common['tracklog']) return; $new_entry = array( 'type' => $type, 'from' => $from, 'msg' => trim($msg), 'age' => empty($age) ? $this->age() : $age ); $this->log['track'][] = empty($error) ? $new_entry : array_merge($new_entry, array( 'error' => $error ) ); } /** * Fix_Sql; Fix the SQL array and return a queryable string * * @param array $sql SQL array * @param string $type Type of fetch * @author Paul Williamson <webmaster@protonage.net> * @access protected * @return string * * The long do statment in the fields case simply strips the field * string into an array and then makes a where clause if needed */ final protected function fix_sql($sql, $Extra = NULL) { if (!is_array($sql)) { $this->track( "error", "fix_sql", "No array found in `{$sql}`." ); return false; } $sql_type = 'SELECT'; foreach ($sql as $type => $value) { switch($type) { case 'delete': $delete = 'DELETE FROM `' . $value . '`'; $sql_type = 'DELETE'; break; //case 'delete' case 'insert': $insert = 'INSERT INTO `' . $value . '` '; $sql_type = 'INSERT'; break; //case 'insert' case 'update': $update = 'UPDATE `' . $value . '`'; $sql_type = 'UPDATE'; break; //case 'insert' case 'set': $sql_set = 'SET ' . $value; break; //case 'insert' case 'value': foreach ($value as $v) { $sql_values .= "'" . addcslashes($v, '\'') . "', "; } $this->list_trim($sql_values); break; //case 'insert' case 'search': $like = "LIKE '%{$value}%'"; break; //case 'search' case 'table': $tables = $sql['table']; $from = 'FROM `' . $tables . '`'; break; //case 'table' case 'field': if (is_null($value)) { $select = '*'; break; } $num_to_wheres = 0; $buf = $value; do { $pre_buf = $buf; for ($i = 0; $i < 2; $i++) { $p = $i ? $this->preg_sql_noquote : $this->preg_sql_quote; $r = $i ? '$4' : '$5'; while(preg_match($p, $buf)) { $fields[] = preg_replace($p, '$1', $buf); $buf = preg_replace($p, $r, $buf); if (preg_match('/=/', end($fields))) $num_to_wheres++; } } if ($buf == $pre_buf) { $this->track( "error", "fix_sql", "Parse error in Fields `{$value}`." ); throw new Exception("Parse error in Fields `{$value}`."); return false; } } while(!empty($buf)); $in_fields = array(); $num_fields = count($fields); for ($i = 0; $i < $num_fields; $i++) { $field = $fields[$i]; if (preg_match('/=/', $field)) { $sql_where .= $this->fix_where($field); } $field = preg_replace( '/(^[a-zA-Z0-9\._]+).*$/i', '$1', $field ); if (array_search($field, $in_fields) === false) { $sql_fields .= '`' . $field . '`, '; } $in_fields[] = $field; } $this->list_trim($sql_where, ' AND '); $this->list_trim($sql_fields); break; //case 'field' case 'order': $order = is_null($value) ? '' : 'ORDER BY ' . $value; break; //case 'order' case 'limit': if (!preg_match('/^[0-9]+(, ?[0-9]+)?$/', $value)) { $limit = $value; } else { $limit = ''; } break; //case 'limit' } //switch($type) } //foreach ($sql as $type => $value) $select = $Extra != 'ALL' ? 'SELECT ' . $sql_fields : 'SELECT *'; $where = !empty($sql_where) ? 'WHERE ' . $sql_where : ''; $insert = $insert . '(' . $sql_fields . ') VALUES (' . $sql_values . ')'; $like = !empty($sql_where) ? $like : 'WHERE ' . $sql_fields . ' ' . $like; switch($sql_type) { case 'SELECT': $query = "{$select} {$from} {$where} {$like} {$order} {$limit}"; break; case 'INSERT': $query = $insert; break; case 'UPDATE': $query = "{$update} {$sql_set} {$where} {$limit}"; break; case 'DELETE': $query = "{$delete} {$where} {$limit}"; break; } return trim(preg_replace('/ +/', ' ', $query)) . ';'; } /** * Fix_Where; Return a where clause with proper MySQL syntax * * @param string $field Field that will be included in where clause * @author Paul Williamson <webmaster@protonage.net> * @access protected * @return string */ protected function fix_where($field) { $parts = preg_split('/ *= */i', $field, 2); $wfield = '`' . str_replace('`', '', $parts[0]) . '`='; // addcslashes to prevent query parse error $wfield .= '\'' . addcslashes( preg_replace('/(^[\'"`])|([\'"`]$)/i', '', $parts[1] ), '\'' ) . '\''; return $wfield . ' AND '; } /** * Fix_List; Return an array of broken elements from a list * seperated by commas and quotes * * @param string $list List to be converted to array * @author Paul Williamson <webmaster@protonage.net> * @access protected * @return array */ protected function fix_list($list) { $buf = $list; $result = array(); do { $pre_buf = $buf; for ($i = 0; $i < 2; $i++) { $q = $i ? preg_replace('/^ *([`\'"]).*/is', '$1', $buf) : ''; $p = $i ? str_replace('{quote}', $q, $this->preg_lst_quote) : $this->preg_lst_noquote; while (preg_match($p, $buf) && !empty($buf)) { $result[] = preg_replace($p, '$1', $buf); $buf = preg_replace($p, '$3', $buf); } } if ($buf == $pre_buf) { $this->track( "error", "fix_list", "Parse error in List `{$list}`." ); throw new Exception("Parse error in List `{$list}`."); return false; } } while(!empty($buf)); return $result; } /** * Set_Param; Set an argument value if already exists * * @param string &$arg Argument varable * @param string $name Argument name * @author Paul Williamson <webmaster@protonage.net> * @access private * @return void */ private function set_param(&$arg, $name) { $arg = (is_null($arg)) ? $this->$name : $arg; if (is_null($arg)) { $this->track('error', 'set_param', 'Parameter `' . $name . '` is not set' ); throw new Exception('Parameter `' . $name . '` is not set'); trigger_error('Parameter `' . $name . '` is not set', E_USER_ERROR); } $this->$name = $arg; } /** * Fetch; Impliment the mysql_fetch_* functions * * @param resource $res Query result * @param int $fetch Fetch Type * @author Paul Williamson <webmaster@protonage.net> * @access protected * @return mixed */ protected function fetch($res, $fetch) { switch ($fetch) { case FETCH_ASSOC: $this->fetch_default = $fetch; return mysql_fetch_assoc($res); break; case FETCH_NUM: $this->fetch_default = $fetch; return mysql_fetch_row($res); break; case FETCH_OBJECT: $this->fetch_default = $fetch; return mysql_fetch_object($res); break; default: return mysql_fetch_assoc($res); } } /** * List_Trim; Trim the end of a list from a loop * * Function will take out extra ', ' on the end of a list string * * @param string &$str String to trim * @author Paul Williamson <webmaster@protonage.net> * @access protected * @return string */ protected function list_trim(&$str, $tpat = ', ') { $preg_trim = '/(.*?)' . $tpat . '$/i'; $str = preg_replace($preg_trim, '$1', $str); return $str; } /** * Kill; Disconnect from database * * @author Paul Williamson <webmaster@protonage.net> * @access private * @return void */ private function kill() { @mysql_close($this->connection); $this->track('event', 'kill', "Connect to {$this->host} has been forced to close." ); } /** * TimeNow; returns the current time * * In PHP 5, microtime() was givin a boolean * param, if true, microtime() would return a float * which is exactly what this function does. * * @author Paul Williamson <webmaster@protonage.net> * @access protected * @return float */ protected function timenow() { /** * For PHP4: * * list($a, $b) = explode(' ', microtime()); * return $a + $b; * * PHP5 makes it less painful with the same result. * Thanks to the new boolean argument provided by microtime() */ return microtime(true); } /** * Age; how long the class has been alive * * @author Paul Williamson <webmaster@protonage.net> * @access protected * @return float microtime */ protected function age() { return $this->timenow()-$this->birth; } /** * Do_FullLog; Write log track array to a file * * @author Paul Williamson <webmaster@protonage.net> * @access private * return void */ /** * Do_Log; Write full log array to a file * * @author Paul Williamson <webmaster@protonage.net> * @access private * return void */ private function do_fulllog() { $path = self::LOG_PATH; if (is_dir($path)) { for ($i = 1; file_exists($file = $path . '/simplesql_raw.' . $i); $i++) { if (filesize($file) < self::MAX_SIZE) break; } if ($handle = fopen($file, 'a')) { $add = '$Id' . serialize($this->log) . '/$Id' . "\n"; if (fwrite($handle, $add) === false) { trigger_error("Cannot write to file `{$file}`.", E_WARNING); } } else { trigger_error("Cannot open file `{$file}` for append.", E_WARNING); } } else { trigger_error("Cannot find path `{$path}`.", E_WARNING); } } /** * Do_Log; Write log track array to a file * * @author Paul Williamson <webmaster@protonage.net> * @access private * return void */ private function do_log() { if (!$this->common['tracklog']) return ; $path = self::LOG_PATH; if (is_dir($path)) { for ($i = 1; file_exists($file = $path . '/simplesql_log.' . $i); $i++) { if (filesize($file) < self::MAX_SIZE) break; } if ($handle = fopen($file, 'a')) { $add = "\n\n========================="; $add .= "\nLog for session ID {$this->log['session']} @ {$this->log['date']}"; $add .= "\n=========================\n"; foreach ($this->log['track'] as $line => $arr) { if (is_int($line)) { $tab = strlen($arr['from']) < 8 ? "\t" : ''; $add .= "\t{$line}: " . strtoupper($arr['type']) . "\t" . strtoupper($arr['from']) . "{$tab}\t{$arr['msg']}\n"; } } if (fwrite($handle, $add) === false) { trigger_error("Cannot write to file `{$file}`.", E_WARNING); } } else { trigger_error("Cannot open file `{$file}` for append.", E_WARNING); } } else { trigger_error("Cannot find path `{$path}`.", E_WARNING); } } /** * PrintLog; Print the log array to the screen * * @author Paul Williamson <webmaster@protonage.net> * @access public * @return void */ public function printlog() { print '<pre>'; print_r($this->log); print '</pre>'; } } // end simplesql ?>