Recently, I started on a new venture in which many sites will be built off the same base files. Pretty much if I change one file it will affect all of my sites. This has its ups and downs, but since the ups outweigh the downs I am going to use it. For this to work in the end, I need to have a good starting point. I won't be able to change method names ect once I add more websites because it will take too much time to update each site.

This is the database class setup I have. It took some time to think up and code, but as of right now it works perfectly and does everything I need it to. I am just wondering what I should add/subtract from it so I won't run into problems later.

FYI: These classes are for PHP5 and will not work in PHP4.

CLASS - class.db.php:

abstract class db {

	public static $_conn = null;

	private static $_table = array();

	public static function start() {
		list( $host,$user,$pass,$name ) = config::get('database->' . ( config::get('production') ? 'limited' : 'full' ) . '->host,user,pass,name');
		self::$_conn = mysql_connect( $host,$user,$pass ) or trigger_error("DB START() - Unable to connect to {$host}",E_USER_ERROR);
		mysql_select_db( $name,self::$_conn ) or trigger_error("DB START() - Unable to select database '{$name}'",E_USER_ERROR);
		destruct::add('database','close');
		destruct::priority('database','after','session');
	}

	public static function close() {
		mysql_close( self::$_conn ) or trigger_error("DB CLOSE() - Unable to terminate connection to database",E_USER_ERROR);
	}

	public static function changeDB( $name ) {
		mysql_select_db( $name,self::$_conn ) or trigger_error("DB CHANGEDB() - Unable to change database to '{$name}'",E_USER_ERROR);
	}

	public static function clean( $data ) {
		return mysql_real_escape_string( trim( $data ),self::$_conn );
	}

	public static function table( $name ) {
		if ( !isset( self::$_table[$name] ) ) {
			self::$_table[$name] = new table( $name );
		}
		return self::$_table[$name];
	}

	public static function execute( $sql ) {
		$query = mysql_query( $sql,self::$_conn ) or trigger_error("DB EXECUTE() - SQL query ({$sql}) failed: " . mysql_error( self::$_conn ),E_USER_ERROR);
		return new mysqlresult( $query );
	}

}

To use on your server, you need to replace the start() function with this one (since you don't have my other classes)

public static function start( $host,$user,$pass,$name ) {
		self::$_conn = mysql_connect( $host,$user,$pass ) or trigger_error("DB START() - Unable to connect to {$host}",E_USER_ERROR);
		mysql_select_db( $name,self::$_conn ) or trigger_error("DB START() - Unable to select database '{$name}'",E_USER_ERROR);
	}

CLASS - class.table.php:

class table {

	private $pk = null;
	private $fields = array();
	private $table = null;
	private $cache = array();
	private $sql = array();

	public function __construct( $table ) {
		$this->table = $table;
		$query = db::execute("DESCRIBE `{$this->table}`");
		while( list( $field,,,$key ) = $query->fetch() ) {
			$this->fields[] = $field;
			if ( $key == 'PRI' ) {
				$this->pk = $field;
				break;
			}
		}
		if ( is_null( $this->pk ) ) {
			trigger_error("TABLE __CONSTRUCT - Table '{$this->table}' does not have a primary key",E_USER_ERROR);
		}
	}

	public function column( $name ) {
		if ( in_array( $name,$this->fields ) ) {
			return true;
		}
		return false;
	}

	public function &cache( $index ) {
		return $this->cache[$index];
	}

	public function bind() {
		$args = func_get_args();
		$types = array_shift( $args );
		$this->sql['bind'] = array(
			'types' => $types,
			'data' => $args
		);
		return $this;
	}

	public function run( $index ) {
		if ( !isset( $this->cache[$index] ) ) {
			return false;
		}
		$this->sql = $this->cache[$index];
		return $this->execute();
	}

	public function query() {
		if ( !empty( $this->sql ) ) {
			trigger_error("TABLE QUERY() - Run 'execute' function before trying to create another query",E_USER_ERROR);
		}
		$num = func_num_args();
		$args = func_get_args();
		$type = array_shift( $args );
		switch( $type ) {
			case "select":
				$query['data'] = $args[0];
				if ( isset( $args[1] ) ) {
					$query['where'] = $args[1];
				}
				if ( isset( $args[2] ) && is_array( $args[2] ) ) {
					$query['extra'] = $args[2];
				}
			break;
			case "update":
				$query['data'] = $args[0];
				$query['where'] = "`{$this->pk}` = ?";
				$this->bind( 's',$args[1] );
			break;
			case "update-multi":
				$type = 'update';
				$query['data'] = $args[0];
				$query['where'] = $args[1];
				if ( isset( $args[2] ) && is_array( $args[2] ) ) {
					$query['extra'] = $args[2];
				}
			break;
			case "insert":
				$query['data'] = $args[0];
			break;
			case "delete":
				$query['where'] = "`{$this->pk}` = ?";
				$this->bind( 's',$args[0] );
				if ( isset( $args[1] ) && is_array( $args[1] ) ) {
					$query['extra'] = $args[1];
				}
			break;
			case "delete-multi":
				$type = 'delete';
				$query['where'] = $args[0];
				if ( isset( $args[1] ) && is_array( $args[1] ) ) {
					$query['extra'] = $args[1];
				}
			break;
			default:
				trigger_error("TABLE QUERY() - Invaild query type '{$type}'",E_USER_ERROR);
			break;
		}
		$query['type'] = $type;
		if ( isset( $query['extra'] ) ) {
			$extra = $query['extra'];
			unset( $query['extra'] );
			$query = array_merge( $query,$extra );
		}
		$this->sql = array_merge( $this->sql,$query );
		return $this;
	}

	private static function readyInsert( $val ) {
		return "'" . db::clean( $val ) . "'";
	}

	private static function readyUpdate( $key,$val ) {
		return "`{$key}` = '" . db::clean( $val ) . "'";
	}

	private function build( $array ) {
		$query = '';
		switch( $array['type'] ) {
			case "select":
				$fields = ( is_array( $array['data'] ) ? implode( ',',$array['data'] ) : $array['data']  );
				$query = "SELECT {$fields} FROM `{$this->table}`";
			break;
			case "insert":
				$fields = implode( ',',array_keys( $array['data'] ) );
				$values = implode( ',',array_map( array( 'table','readyInsert' ),array_values( $array['data'] ) ) );
				$query = "INSERT INTO `{$this->table}` ({$fields}) VALUES ({$values})";
			break;
			case "update":
				$fields = implode( ',',array_map( array( 'table','readyUpdate' ),array_keys( $array['data'] ),array_values( $array['data'] ) ) );
				$query = "UPDATE `{$this->table}` SET {$fields}";
			break;
			case "delete":
				$query = "DELETE FROM `{$this->table}`";
			break;
			default:
				trigger_error("TABLE BUILD() - Invalid query type '{$array['type']}'",E_USER_ERROR);
			break;
		}
		$str = '';
		$parts = array( 'where','order by','group by','having','limit' );
		foreach( $parts as $part ) {
			if ( isset( $array[$part] ) ) {
				$str .= ' ' . strtoupper( $part ) . ' ' . $array[$part];
			}
		}
		$query = $query . $str;
		if ( isset( $array['bind'] ) ) {
			$types = str_split( $array['bind']['types'] );
			foreach( $types as $i => $type ) {
				$str = '';
				switch( $type ) {
					case "i":
						$str = "%d";
					break;
					case "b":
					case "d":
					case "u":
					case "o":
						$str = "%{$type}";
					break;
					case "c":
					case "e":
					case "f":
					case "s":
					case "x":
					case "X":
						$str = "'%{$type}'";
					break;
					case "a":
						$str .= "'" . serialize( $array['bind']['data'][$i] ) . "'";
						unset( $array['bind']['data'][$i] );
					break;
					default:
						trigger_error("TABLE BUILD() - Invalid data type '{$type}'",E_USER_ERROR);
					break;
				}
				if ( $pos = strpos( $query,'?' ) ) {
					$query = substr_replace( $query,$str,$pos,1 );
				}
			}
			array_unshift( $array['bind']['data'],$query );
			$query = call_user_func_array( 'sprintf',$array['bind']['data'] );
		}
		return $query;
	}

	public function save( $index ) {
		if ( is_null( $this->sql ) ) {
			trigger_error("TABLE SAVE() - Please build a query before trying to save it",E_USER_ERROR);
		}
		$this->cache[$index] = $this->sql;
		$this->sql = array();
		return true;
	}

	public function execute() {
		$sql = $this->sql;
		$query = $this->build( $sql );
		$this->sql = array();
		return db::execute( $query,$sql['type'] );
	}

}

CLASS - class.mysqlresult.php:

class mysqlresult {

	private $query;
	private $type = null;

	public $insert_id = null;
	public $num_rows = null;
	public $affected_rows = null;

	public function __construct( $query,$type ) {
		$this->query = $query;
		$this->type = $type;
		switch( $this->type ) {
			case "insert":
				$this->insert_id = $this->insertID();
			case "update":
			case "delete":
				$this->affected_rows = $this->affectedRows();
			break;
			case "select":
				$this->num_rows = $this->numRows();
			break;
		}
	}

	public function __destruct() {
		if ( is_resource( $this->query ) ) {
			mysql_free_result( $this->query );
		}
	}

	public function fetch() {
		return mysql_fetch_array( $this->query );
	}

	public function fetchAll() {
		$fetch = array();
		while( $row = $this->fetch() ) {
			$fetch[] = $row;
		}
		return $fetch;
	}

	public function fetchAssoc() {
		return mysql_fetch_assoc( $this->query );
	}

	public function fetchRow() {
		return mysql_fetch_row( $this->query );
	}

	public function insertID() {
		return mysql_insert_id( db::$_conn );
	}

	public function numRows() {
		return mysql_num_rows( $this->query );
	}

	public function affectedRows() {
		return mysql_affected_rows( db::$_conn );
	}

}

I didn't use the mysqli class because it didn't work as expected. I like the the bind_param functionality, but the way you have to define variables and assign values later by reference was annoying and caused problems. Also, fetching results was a pain in the ***.

Here as some usage examples:

//Select all data from a table named 'test'
$query = db::table('test')->query('select','*')->execute();

//Select certain fields in table named 'test'
$query = db::table('test')->query('select',array('id','name'))->execute();

//Select statement with where clause, this selects the id and name columns from the row with the id of 1
$query = db::table('test')->query('select',array('id','name'),'`id` = 1')->execute();

//Update and delete examples. This uses the primary key of the table to delete records. This really helps simplify some database calls
$data = array(
	'name' => 'new name'
);
$query = db::table('test')->query('update',$data,1)->execute(); //this will update the row with id of 1 with a new name value.
$query = db::table('test')->query('update-multi',$data,"`value` = 'something' AND `other` = 'something'")->execute(); //update with where clause (usually used when update multiple rows or a row without using the primary key

$query = db::table('test')->query('delete',1)->execute(); deletes a row with the primary key column value of 1
$query = db::table('test')->query('delete-multi',"`value` = 'asdfas'")->execute(); //same as the update-multi, just deletes

//Insert example. just create an array with column names as keys and the value you want
$data = array(
	'name' => 'name',
	'data' => 'data'
);
$query = db::table('test')->query('insert',$data)->execute();

//Extra query elements like 'limit', 'order by', 'group by', 'having', ect. can be added by array (for ease of use) as the last param of the query function. it works for select,update-multi,delete-multi queries. if there is no where clause please fill the param with 'null'
$query = db::table('test')->query('select','*','where clause or null',array('limit'=>5,'order by'=>'`id` DESC'))->execute();

//Using the bind functionality
$value = 'Testing';
$query = db::table('test')->query('select','*','`column` = ? AND `id` = ?')->bind('si',$value,1)->execute(); //works almost the same as mysqli bind_param.
//bind works for select,update-multi,delete-multi queries.

//Using the save function
//You can save any query for specific table, just replace execute() with save(). you must provide an id to save with.
db::table('test')->query('select','*','`column` = ?')->bind('s','value')->save('test_select');

//you can execute this with the run function
$query = db::table('test')->run('test_select');

//you can get saved queries from the cache using the cache function
$query =& db::table('test')->cache('test_select');
$query['limit'] = '0, 5';
//after this is done you can send this to other classes or functions to change query properties like limit and order by. its all done by reference so you want have to redo the query, just use the run function.

//Getting query data

$query->fetch(); //same things as mysql_fetch_array()
while( $row = $query->fetch() ) { //example usage
	print_r( $row );
}

$query->fetchAll(); //gets all data at once

$query->fetchAssoc(); //same as mysql_fetch_assoc()

$query->fetchRow(); //same as mysql_fetch_row()

$query->affectedRows(); //same as mysql_affected_rows(). this only works on insert,update,and delete queries
//or
$query->affected_rows;

$query->numRows(); //same as mysql_num_rows(). this only works for select queries
//or
$query->num_rows

$query->insertID(); //same as mysql_insert_id(). this only works for insert queries
//or
$query->insert_id;

Recommended Answers

All 6 Replies

To be honest I skimmed your php files. If you don't mind could you use the PHP code tag. Makes reading them much easier.

In my opinion I think you are over complicating this. I have done the same concept off of 1 database class i wrote. Mind you, yours is more complex.

One thing I wanted to point out was the clean method. Since this is all on one server this many not be important but just tossing this your way.

if(get_magic_quotes_gpc()){
	$data = stripslashes($data);
}
return mysql_real_escape_string($data);

For fun and criticism I provided my database.class.php file.
The way I handled multiple sites was through a config conditional script that would load the proper database depending on the passed url. All sites used the same database structure only database names changed. Tables and everything else were the same.

<?php
/**
 * @version $Id: database.class.php 100 2009-01-14 00:22:48Z Jeremy Simkins $
 * @copyright (c) 2008 Jeremy Simkins
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 */

/**
 * @IGNORE
 */
if (!defined('IN_PLATFORM')) { die('Page not found: Error 404'); }

class Database {
	var $server   = ''; //database server address
	var $user     = ''; //database login name
	var $pass     = ''; //database login password
	var $database = ''; //database name
	var $pre      = ''; //database table prefix (not required)

	// Internal Info
	var $record = array();
	var $error 	= '';
	var $errno 	= 0;
	var $recent_query 	= '';
	var $num_queries	= 0;

	var $field_table	= ''; // Table name affected by SQL query
	var $affected_rows 	= 0; // Number of rows affected by SQL query
	var $query_id 		= 0;
	var $sql_link 		= false; // connection status
	var $show_errors 	= true; // You can use your own error display function if you have one, or set this to true.

	var $sqlArray = array();

	// The Constructor
	function Database( $server, $user, $pass, $database, $pre = '' ) {
		$this->server	= $server;
		$this->user		= $user;
		$this->pass		= $pass;
		$this->database	= $database;
		$this->pre		= $pre;
	}

	// Standard connect
	function connect() {
		// Check to see if we are already connected
		if(!$this->sql_link) {
			$this->sql_link = mysql_connect($this->server,$this->user,$this->pass);

			if (!$this->sql_link) { // Connect failed
				if ($this->show_errors) {
					$this->error_msg("Could not connect to server: <b>$this->server</b>.");
				} else {
					return false;
				}

			}

			if(!mysql_select_db( $this->database, $this->sql_link )) {//no database
				if ($this->show_errors) {
					$this->error_msg("Could not open database: <b>$this->database</b>.");
				} else {
					return false;
				}
			}

			// unset the data so it can't be dumped
			$this->server	= '';
			$this->user		= '';
			$this->pass		= '';
			$this->database	= '';

		} else { // We are already connected so we exit out of here
			exit();
		}
	}


	// Standard close connection
	function close() {
		if(!mysql_close($this->sql_link)){
			if ($this->show_errors) {
				$this->error_msg('Close Connection Failed.');
			} else {
				return false;
			}
		}
	}


	/**
	 * Escapes character to be MySQL ready
	 *
	 * @param string $string
	 * @return string
	 */
	function escape($string) {
		if(get_magic_quotes_gpc()){
			$string = stripslashes($string);
		}
		return mysql_real_escape_string($string);
	}


	/**
	 * Executes SQL query
	 *
	 * @param string $sql
	 * @return int - query_id
	 */
	function query($sql) {
		if(empty($this->sql_link)) { // We make sure we have a connection first
			$this->connect();
		}

		$sql = trim($sql);
		$this->recent_query = $sql;
		$start = microtime();

		// Process query
		$this->query_id = mysql_query($sql, $this->sql_link);

		if (!$this->query_id) {
			return false;
		}

		if ( (substr($sql, 0, 6) == 'SELECT') || (substr($sql, 0, 4) == 'SHOW') ) { // SELECT || SHOW
			$this->affected_rows = mysql_num_rows($this->query_id);
		} else {
			$this->affected_rows = mysql_affected_rows($this->sql_link);
		}
		$this->num_queries += 1;

		if (!preg_match('/^(UPDATE|INSERT|DELETE|SHOW|TRUNCATE)/i', $this->recent_query)) {
			$this->sqlArray[] = array('start' => $start, 'end' => microtime(), 'sql' => ($this->recent_query) );
		}
		return $this->query_id;
	}


	/**
	 * Fetch a result row as an associative array
	 *
	 * @param int $query_id
	 * @return array - fetched row
	 */
	function fetchrow($query_id = false) {
		// Fetch row
		if ($query_id) {
			$this->query_id = $query_id;
		}

		if (isset($this->query_id)) {
			$this->record = mysql_fetch_assoc($this->query_id);
		} else {
			return false;
		}

		// Unescape record
		if($this->record){
			$this->record = array_map('stripslashes', $this->record);
		}
		return $this->record;
	}


	/**
	 * Fetch all rows of a query
	 *
	 * @param string $sql
	 * @return array - Assoc array of results
	 */
	function fetchrowset( $sql ) {
		$out = array();
		$query_id = $this->query($sql);

		while ($row = $this->fetchrow()){
			$out[] = $row;
		}
		$this->freeresult($query_id);
		return $out;
	}


	/**
	 * Fetch a result row as an object
	 *
	 * @param string $sql
	 * @param int $query_id
	 * @return object
	 */
	function object( $sql, $query_id = false ) {
		$sql = trim($sql);

		if( $sql ) {
			$this->query($sql);
			$obj = mysql_fetch_object($this->query_id);
		} else if ($query_id) {
			$obj = mysql_fetch_object($query_id);
		} else if (empty($sql) && empty($query_id)) {
			$obj = mysql_fetch_object($this->query_id);
		}
		//		$this->freeresult( $this->query_id );
		return $obj;
	}



	/**
	 * Free result memory
	 *
	 * @param int $query_id - If not specified, last used
	 */
	function freeresult( $query_id = false ) {
		if ( $query_id ) {
			$this->query_id=$query_id;
		}
		if( !mysql_free_result( $this->query_id ) ) {
			if ($this->show_errors) {
				$this->error_msg("Result ID: <b>$this->query_id</b> could not be freed.");
			} else {
				return false;
			}
		}
	}


	/**
	 * Fetches first row of the query
	 *
	 * @param string $query_string
	 * @return array
	 */
	function fetch_firstrow( $query_string ) {
		$query_id = $this->query( $query_string );
		$out = $this->fetchrow( $query_id );
		$this->freeresult( $query_id );
		return $out;
	}


	/**
	 * Builds an update query
	 *
	 * @param string $table
	 * @param array $data
	 * @param string $where
	 * @param bool $allowInsert
	 * @return int
	 */
	function update( $table, $data, $where = '1', $allowInsert = false ) {
		$query = 'UPDATE '.$table.' SET ';

		foreach ( $data as $key=>$val ) {
			if (strtolower($val) == 'null') {
				$query.= "$key = NULL, ";
			} else if (strtolower($val) == 'now()') {
				$query.= "$key = NOW(), ";
			} else {
				$query.= "$key = '".$this->escape($val)."', ";
			}
		}
		$query = rtrim( $query, ', ') . ' WHERE '.$where.';';

		if ( $allowInsert ) {
			$result = $this->query( $query );
			if ( $result ) {
				return $result;
			} else {
				$this->insert( $table, $data );
			}
		} else {
			return $this->query($query);
		}
	}



	/**
	 * Builds an INSERT INTO query off the passed table and the data array
	 *
	 * @param string $table
	 * @param array $data
	 * @param bool $forceFreeResult
	 * @return int
	 */
	function insert( $table, $data, $forceFreeResult = false ) {
		$keys	= '';
		$values	= '';
		$query = 'INSERT INTO '.$table.' ';

		if ( !is_array($data) ) {
			if ($this->show_errors) {
				$this->error_msg("The values being passed need to be in an array");
			} else {
				return false;
			}
		}

		foreach ($data as $key=>$val) {
			$keys .= "$key, ";
			if (strtolower($val) == 'null') {
				$values .= 'NULL, ';
			} else if (strtolower($val) == 'now()') {
				$values .= 'NOW(), ';
			} else {
				$values .= "'".$this->escape($val)."', ";
			}
		}
		$query .= '( '. rtrim( $keys, ', ') .' ) VALUES ( '. rtrim( $values, ', ') .' );';

		if($this->query( $query )){
			$newID = mysql_insert_id($this->sql_link);
			if ( $forceFreeResult ) {
				$this->freeresult();
			}
			return $newID;
		} else {
			return false;
		}
	}



	function queriesExplained () {
		global $lang;

		if ($_SESSION['type'] < SYSTEM_MOD) {
			return;
		}

		function convert_microtime($time)
		{
			list($usec, $sec) = explode(' ', $time);
			return ( (float)$usec + (float)$sec );
		}

		$trc_sql = $this->sqlArray;
		$count_trc_sql = count($trc_sql);

		echo '<table cellpadding="2" border="0" cellspacing="1" width="100%" align="center" class="explain-main">';
		for ( $i = 0; $i < $count_trc_sql; $i++ )
		{
			if ( !preg_match('/^(UPDATE|INSERT|DELETE|SHOW|TRUNCATE)/i', $trc_sql[$i]['sql']) )
			{
				// get explainations
				$sql = 'EXPLAIN ' . $trc_sql[$i]['sql'];
				$result = $this->query($sql);

				$totalParseTime = ($trc_sql[$i]['end'] - $trc_sql[$i]['start']);

				$first_table = true;
				$explain_color = false;

				echo '<tr>';
				echo '<td colspan="10">';
				echo '<br />';
				echo '&nbsp;'.$lang['REQUEST'].'&nbsp;:&nbsp;<strong>'.$trc_sql[$i]['sql'].'</strong>';
				echo '</td>';
				echo '</tr>';

				echo '<tr>';
				echo '<td colspan="10">';
				echo '&nbsp;'.sprintf($lang['STAT_DUR'], $totalParseTime);
				echo '</td>';
				echo '</tr>';

				echo '<tr>';
				echo '<td>';
				while ( $row = $this->fetchrow($result) )
				{
					echo '<table cellpadding="2" border="1" cellspacing="1" width="100%" align="center" class="explain-legend">';

					// Build the Legend
					echo '<tr>';
					foreach ( $row as $key=>$value )
					{
						if ( !is_integer($key) )
						{
							echo '<td align="center">'.(isset($lang['STAT_' . strtoupper($key)]) ? $lang['STAT_' . strtoupper($key)] : str_replace('_', ' ', $key)).'</td>';

						}
					}
					echo '</tr>';

					echo '<tr>';
					foreach ( $row as $key=>$value )
					{
						if ( !is_integer($key) )
						{
							echo '<td align="center"><strong>'.(isset($value) ? $value : '&nbsp;').'</strong>&nbsp;</td>';
						}
					}
					echo '</tr>';

					echo '</table>';
				}
				echo '</td>';
				echo '</tr>';
			}
		}
		echo '</table>';
	}

	/**
	 * Displays an error message
	 *
	 * @param string $msg
	 */
	function error_msg( $msg = '' ) {
		if ( $this->sql_link ){
			$this->error = mysql_error( $this->sql_link );
			$this->errno = mysql_errno( $this->sql_link );
		} else {
			$this->error = mysql_error();
			$this->errno = mysql_errno();
		}

		echo '<table align="center" border="1" cellspacing="0" style="background:white;color:black;width:80%;">';
		echo '<tr><th colspan=2>Database Error</th></tr>';
		echo '<tr><td align="right" valign="top">Message:</td><td>'.$msg.'</tr></td>';

		if($this->error) {
			echo '<tr><td align="right" valign="top" nowrap>MySQL Error '.(($this->errno) ? $this->errno : '').':</td><td>'.$this->error.'</tr></td>';
		}

		echo '<tr><td align="right">Date:</td><td>'.date("l, F j, Y \a\\t g:i:s A").'</tr></td>';
		echo '<tr><td align="right">Script:</td><td><a href="'.$_SERVER['REQUEST_URI'].'">'.$_SERVER['REQUEST_URI'].'</a></tr></td>';

		if ( isset($_SERVER['HTTP_REFERER']) && $_SERVER['HTTP_REFERER'] ) {
			echo '<tr><td align="right">Referer:</td><td><a href="'.$_SERVER['HTTP_REFERER'].'">'.$_SERVER['HTTP_REFERER'].'</a></tr></td>';
		}
		echo '</table>';
	}
}

?>

I ran out of time to make changes so I can't change it to php syntax.

As for the magic quotes, the database class is part of a bigger framework with makes sure that setting is properly set for the server. I don't need to worry about it.

Also, I noticed an error with my files. I got data from an older file that hadn't updated yet, so the code is wrong. Here is the new class.db.php:

abstract class db {

	public static $_conn = null;

	private static $_table = array();

	public static function start() {
		list( $host,$user,$pass,$name ) = config::get('database->' . ( config::get('production') ? 'limited' : 'full' ) . '->host,user,pass,name');
		self::$_conn = mysql_connect( $host,$user,$pass ) or trigger_error("DB START() - Unable to connect to {$host}",E_USER_ERROR);
		mysql_select_db( $name,self::$_conn ) or trigger_error("DB START() - Unable to select database '{$name}'",E_USER_ERROR);
		destruct::add('database','close');
		destruct::priority('database','after','session');
	}

	public static function close() {
		mysql_close( self::$_conn ) or trigger_error("DB CLOSE() - Unable to terminate connection to database",E_USER_ERROR);
	}

	public static function changeDB( $name ) {
		mysql_select_db( $name,self::$_conn ) or trigger_error("DB CHANGEDB() - Unable to change database to '{$name}'",E_USER_ERROR);
	}

	public static function clean( $data ) {
		return mysql_real_escape_string( trim( $data ),self::$_conn );
	}

	public static function table( $name ) {
		if ( !isset( self::$_table[$name] ) ) {
			self::$_table[$name] = new table( $name );
		}
		return self::$_table[$name];
	}

	public static function execute( $sql,$type=null ) {
		$query = mysql_query( $sql,self::$_conn ) or trigger_error("DB EXECUTE() - SQL query ({$sql}) failed: " . mysql_error( self::$_conn ),E_USER_ERROR);
		return new mysqlresult( $query,$type );
	}

}

Any reason why it's defined as abstract, do you plan on extending it later to support different DBs? Also, as a style thing, usually classes start with a capital letter and the names are CamelCased. Secondly, you might want to make _conn private given that you have public functions to open and close a connection.

Its abstract because I don't want to have anyone create an instance of it. Theres only one connection to the database, so there is no reason to have more than one instance or in this case none.

I used the singleton method a few months back for this, but sometimes it was annoying to have to call app::load('database')->table('mem_data')->.... for simple things. Now all I have to do is db::table which is simpler. Usually I wouldn't worry so much about the only one instance stuff (or none because I went static with everything), but many people could be working on my project after its completed and I want to make sure they do things as they were meant to be done.

I don't plan on extending it, I don't have much knowledge in other database types. If I add another database to it, I will probably just make a change to the classes to handle it.

The style I use is out of personal preference. My code has to be as simple as possible and meet a certain look to it (I don't know why, OCD maybe?). I like the uniform look of all lower-case letters.

The connection is public because the mysqlresult class uses it for insertID and affectedRows to prevent some errors.

If you don't want it instantiated then throw an exception if the constructor is called. An abstract exists to be extended, that's why you can't instantiate them.

As for the public conn, you can make it private, just add getConn/setConn methods.

EDIT: Forgot to mention, what is all this stuff?

destruct::add('database','close');
destruct::priority('database','after','session');

In the beginning I had the class throw an error when the constructor was called, but I looked around and saw that defining it as abstract was the fix for it. Maybe I misunderstood the point of abstract, I just followed what I read.

I created a class to handle the destruct order of classes. Since I use a database to store my sessions, I was having a problem where the database destruct method was being called before the session destruct meaning that my sessions were not being written to the database because the connection had already been closed. Those functions ensure that session will be called before database.

Thanks for pointing those out. I forgot to change database to db since I changed the class name.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.