WordPress Database Connection Class Tutorial

In this tutorial, I hope to cover the proper way to connect to the WordPress MySQL table and process queries. I loved the wp-db.php include file. The way the code is set up makes it super easy to process queries for your plug-ins. The file that is used is wp-db.php and is in the “includes” folder. Lets begin by showing you the code:

<?php
/**
 * WordPress DB Class
 *
 * Original code from {@link http://php.justinvincent.com Justin Vincent (justin@visunet.ie)}
 *
 * @package WordPress
 * @subpackage Database
 * @since 0.71
 */
 
/**
 * @since 0.71
 */
define('EZSQL_VERSION', 'WP1.25');
 
/**
 * @since 0.71
 */
define('OBJECT', 'OBJECT', true);
 
/**
 * @since {@internal Version Unknown}}
 */
define('OBJECT_K', 'OBJECT_K', false);
 
/**
 * @since 0.71
 */
define('ARRAY_A', 'ARRAY_A', false);
 
/**
 * @since 0.71
 */
define('ARRAY_N', 'ARRAY_N', false);

This is the first part of the code, it creating some of the code that will be needed later on. A lot of times, we will be specifying how we want to receive data from our queries. WordPress gives you 3 options most of the time: numeric arrays, associative arrays, or as an object. You will specify them using the defined variables set forth here in this previous snippet of code. This will make it easier for the average coder to use the info that they receive.

Let’s continue viewing the code and see how the class starts:

/**
 * WordPress Database Access Abstraction Object
 *
 * It is possible to replace this class with your own
 * by setting the $wpdb global variable in wp-content/db.php
 * file with your class. You can name it wpdb also, since
 * this file will not be included, if the other file is
 * available.
 *
 * @link http://codex.wordpress.org/Function_Reference/wpdb_Class
 *
 * @package WordPress
 * @subpackage Database
 * @since 0.71
 * @final
 */
class wpdb {
 
	/**
	 * Whether to show SQL/DB errors
	 *
	 * @since 0.71
	 * @access private
	 * @var bool
	 */
	var $show_errors = false;
 
	/**
	 * Whether to suppress errors during the DB bootstrapping.
	 *
	 * @access private
	 * @since {@internal Version Unknown}}
	 * @var bool
	 */
	var $suppress_errors = false;
 
	/**
	 * The last error during query.
	 *
	 * @since {@internal Version Unknown}}
	 * @var string
	 */
	var $last_error = '';
 
	/**
	 * Amount of queries made
	 *
	 * @since 1.2.0
	 * @access private
	 * @var int
	 */
	var $num_queries = 0;
 
	/**
	 * Saved result of the last query made
	 *
	 * @since 1.2.0
	 * @access private
	 * @var array
	 */
	var $last_query;
 
	/**
	 * Saved info on the table column
	 *
	 * @since 1.2.0
	 * @access private
	 * @var array
	 */
	var $col_info;
 
	/**
	 * Saved queries that were executed
	 *
	 * @since 1.5.0
	 * @access private
	 * @var array
	 */
	var $queries;
 
	/**
	 * WordPress table prefix
	 *
	 * You can set this to have multiple WordPress installations
	 * in a single database. The second reason is for possible
	 * security precautions.
	 *
	 * @since 0.71
	 * @access private
	 * @var string
	 */
	var $prefix = '';
 
	/**
	 * Whether the database queries are ready to start executing.
	 *
	 * @since 2.5.0
	 * @access private
	 * @var bool
	 */
	var $ready = false;
 
	/**
	 * WordPress Posts table
	 *
	 * @since 1.5.0
	 * @access public
	 * @var string
	 */
	var $posts;
 
	/**
	 * WordPress Users table
	 *
	 * @since 1.5.0
	 * @access public
	 * @var string
	 */
	var $users;
 
	/**
	 * WordPress Categories table
	 *
	 * @since 1.5.0
	 * @access public
	 * @var string
	 */
	var $categories;
 
	/**
	 * WordPress Post to Category table
	 *
	 * @since 1.5.0
	 * @access public
	 * @var string
	 */
	var $post2cat;
 
	/**
	 * WordPress Comments table
	 *
	 * @since 1.5.0
	 * @access public
	 * @var string
	 */
	var $comments;
 
	/**
	 * WordPress Links table
	 *
	 * @since 1.5.0
	 * @access public
	 * @var string
	 */
	var $links;
 
	/**
	 * WordPress Options table
	 *
	 * @since 1.5.0
	 * @access public
	 * @var string
	 */
	var $options;
 
	/**
	 * WordPress Post Metadata table
	 *
	 * @since {@internal Version Unknown}}
	 * @access public
	 * @var string
	 */
	var $postmeta;
 
	/**
	 * WordPress User Metadata table
	 *
	 * @since 2.3.0
	 * @access public
	 * @var string
	 */
	var $usermeta;
 
	/**
	 * WordPress Terms table
	 *
	 * @since 2.3.0
	 * @access public
	 * @var string
	 */
	var $terms;
 
	/**
	 * WordPress Term Taxonomy table
	 *
	 * @since 2.3.0
	 * @access public
	 * @var string
	 */
	var $term_taxonomy;
 
	/**
	 * WordPress Term Relationships table
	 *
	 * @since 2.3.0
	 * @access public
	 * @var string
	 */
	var $term_relationships;
 
	/**
	 * List of WordPress tables
	 *
	 * @since {@internal Version Unknown}}
	 * @access private
	 * @var array
	 */
	var $tables = array('users', 'usermeta', 'posts', 'categories', 'post2cat', 'comments', 'links', 'link2cat', 'options',
			'postmeta', 'terms', 'term_taxonomy', 'term_relationships');
 
	/**
	 * Format specifiers for DB columns. Columns not listed here default to %s.  Initialized in wp-settings.php.
	 *
	 * Keys are colmn names, values are format types: 'ID' => '%d'
	 *
	 * @since 2.8.0
	 * @see wpdb:prepare()
	 * @see wpdb:insert()
	 * @see wpdb:update()
	 * @access public
	 * @war array
	 */
	var $field_types = array();
 
	/**
	 * Database table columns charset
	 *
	 * @since 2.2.0
	 * @access public
	 * @var string
	 */
	var $charset;
 
	/**
	 * Database table columns collate
	 *
	 * @since 2.2.0
	 * @access public
	 * @var string
	 */
	var $collate;
 
	/**
	 * Whether to use mysql_real_escape_string
	 *
	 * @since 2.8.0
	 * @access public
	 * @var bool
	 */
	var $real_escape = false;

Ok, this is a lot of code. Most of it is comments about the variables of the class. The comments are very important because they describe what the variables are there for, and what they do. They also tell you what functions these variables will be used in, and possibly how they are used. For the most part, you don’t really need to concern yourself with these variables just yet, as we are just going over basic CRUD database operations.

The next snippet is the creation/_construct() of the class:

/**
	 * Connects to the database server and selects a database
	 *
	 * PHP4 compatibility layer for calling the PHP5 constructor.
	 *
	 * @uses wpdb::__construct() Passes parameters and returns result
	 * @since 0.71
	 *
	 * @param string $dbuser MySQL database user
	 * @param string $dbpassword MySQL database password
	 * @param string $dbname MySQL database name
	 * @param string $dbhost MySQL database host
	 */
	function wpdb($dbuser, $dbpassword, $dbname, $dbhost) {
		return $this->__construct($dbuser, $dbpassword, $dbname, $dbhost);
	}
 
	/**
	 * Connects to the database server and selects a database
	 *
	 * PHP5 style constructor for compatibility with PHP5. Does
	 * the actual setting up of the class properties and connection
	 * to the database.
	 *
	 * @since 2.0.8
	 *
	 * @param string $dbuser MySQL database user
	 * @param string $dbpassword MySQL database password
	 * @param string $dbname MySQL database name
	 * @param string $dbhost MySQL database host
	 */
	function __construct($dbuser, $dbpassword, $dbname, $dbhost) {
		register_shutdown_function(array(&$this, "__destruct"));
 
		if ( defined('WP_DEBUG') and WP_DEBUG == true )
			$this->show_errors();
 
		if ( defined('DB_CHARSET') )
			$this->charset = DB_CHARSET;
 
		if ( defined('DB_COLLATE') )
			$this->collate = DB_COLLATE;
 
		$this->dbh = @mysql_connect($dbhost, $dbuser, $dbpassword, true);
		if (!$this->dbh) {
			$this->bail(sprintf(/*WP_I18N_DB_CONN_ERROR*/"
<h1>Error establishing a database connection</h1>
<p>This either means that the username and password information in your <code>wp-config.php</code> file is incorrect or we can't contact the database server at <code>%s</code>. This could mean your host's database server is down.</p>
<ul>
	<li>Are you sure you have the correct username and password?</li>
	<li>Are you sure that you have typed the correct hostname?</li>
	<li>Are you sure that the database server is running?</li>
</ul>
<p>If you're unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href='http://wordpress.org/support/'>WordPress Support Forums</a>.</p>
"/*/WP_I18N_DB_CONN_ERROR*/, $dbhost));
			return;
		}
 
		$this->ready = true;
 
		if ( $this->has_cap( 'collation' ) ) {
			if ( !empty($this->charset) ) {
				if ( function_exists('mysql_set_charset') ) {
					mysql_set_charset($this->charset, $this->dbh);
					$this->real_escape = true;
				} else {
					$collation_query = "SET NAMES '{$this->charset}'";
					if ( !empty($this->collate) )
						$collation_query .= " COLLATE '{$this->collate}'";
					$this->query($collation_query);
				}
			}
		}
 
		$this->select($dbname);
	}

So we have 2 functions with a ton of comments. In newer versions of PHP, you can specify a function to be run when a class is created with the _construct() function. In older versions of PHP you had to have the function named after the class for it to be run when the class was created, so in this case it is called wpdb(). They made this class compatible with both PHP4 and PHP5 because they are making it universal. The wpdb function just takes the variables that were entered and passes it along to the _construct() function. The variables required in this function are very self explanatory. It’s simple database connection variables. To connect to a database you simply would type: $dbcon=new wpdb("mysqluser", "mysqlpass", "databasename", "mysqlhost (typically localhost)"); All you would replace is the those variables with your site specific variables and you have your connection. If there are any errors, it will be displayed to you what the error is, such as not having a correct password, or a typo in the user name.

The next function in the list is the _destruct() function, which basically lets you know that the variable no longer exists.

/**
	 * PHP5 style destructor and will run when database object is destroyed.
	 *
	 * @since 2.0.8
	 *
	 * @return bool Always true
	 */
	function __destruct() {
		return true;
	}

There isn’t anything you need to know about this function, so let’s continue to the next function.

	/**
	 * Sets the table prefix for the WordPress tables.
	 *
	 * Also allows for the CUSTOM_USER_TABLE and CUSTOM_USER_META_TABLE to
	 * override the WordPress users and usersmeta tables that would otherwise be determined by the $prefix.
	 *
	 * @since 2.5.0
	 *
	 * @param string $prefix Alphanumeric name for the new prefix.
	 * @return string|WP_Error Old prefix or WP_Error on error
	 */
	function set_prefix($prefix) {
 
		if ( preg_match('|[^a-z0-9_]|i', $prefix) )
			return new WP_Error('invalid_db_prefix', /*WP_I18N_DB_BAD_PREFIX*/'Invalid database prefix'/*/WP_I18N_DB_BAD_PREFIX*/);
 
		$old_prefix = $this->prefix;
		$this->prefix = $prefix;
 
		foreach ( (array) $this->tables as $table )
			$this->$table = $this->prefix . $table;
 
		if ( defined('CUSTOM_USER_TABLE') )
			$this->users = CUSTOM_USER_TABLE;
 
		if ( defined('CUSTOM_USER_META_TABLE') )
			$this->usermeta = CUSTOM_USER_META_TABLE;
 
		return $old_prefix;
	}
 
	/**
	 * Selects a database using the current database connection.
	 *
	 * The database name will be changed based on the current database
	 * connection. On failure, the execution will bail and display an DB error.
	 *
	 * @since 0.71
	 *
	 * @param string $db MySQL database name
	 * @return null Always null.
	 */
	function select($db) {
		if (!@mysql_select_db($db, $this->dbh)) {
			$this->ready = false;
			$this->bail(sprintf(/*WP_I18N_DB_SELECT_DB*/'
<h1>Can&#8217;t select database</h1>
<p>We were able to connect to the database server (which means your username and password is okay) but not able to select the <code>%1$s</code> database.</p>
<ul>
<li>Are you sure it exists?</li>
<li>Does the user <code>%2$s</code> have permission to use the <code>%1$s</code> database?</li>
<li>On some systems the name of your database is prefixed with your username, so it would be like <code>username_%1$s</code>. Could that be the problem?</li>
</ul>
<p>If you don\'t know how to setup a database you should <strong>contact your host</strong>. If all else fails you may find help at the <a href="http://wordpress.org/support/">WordPress Support Forums</a>.</p>'/*/WP_I18N_DB_SELECT_DB*/, $db, DB_USER));
			return;
		}
	}

We continue with setup here. Both of these functions are in place to setup the connection when you first create your connection. It could be important if you are working with a completely different database and need to switch between them, but that isn’t something a lot of people using plug-ins will be doing.

These next functions start to get interesting. The following set of functions prepare queries to be executed by adding slashes and “escaping” the string.

function _weak_escape($string) {
		return addslashes($string);
	}
 
	function _real_escape($string) {
		if ( $this->dbh && $this->real_escape )
			return mysql_real_escape_string( $string, $this->dbh );
		else
			return addslashes( $string );
	}
 
	function _escape($data) {
		if ( is_array($data) ) {
			foreach ( (array) $data as $k => $v ) {
				if ( is_array($v) )
					$data[$k] = $this->_escape( $v );
				else
					$data[$k] = $this->_real_escape( $v );
			}
		} else {
			$data = $this->_real_escape( $data );
		}
 
		return $data;
	}
 
	/**
	 * Escapes content for insertion into the database using addslashes(), for security
	 *
	 * @since 0.71
	 *
	 * @param string|array $data
	 * @return string query safe string
	 */
	function escape($data) {
		if ( is_array($data) ) {
			foreach ( (array) $data as $k => $v ) {
				if ( is_array($v) )
					$data[$k] = $this->escape( $v );
				else
					$data[$k] = $this->_weak_escape( $v );
			}
		} else {
			$data = $this->_weak_escape( $data );
		}
 
		return $data;
	}
 
	/**
	 * Escapes content by reference for insertion into the database, for security
	 *
	 * @since 2.3.0
	 *
	 * @param string $s
	 */
	function escape_by_ref(&$string) {
		$string = $this->_real_escape( $string );
	}

You will probably never call on these functions by themselves as other functions later on call them when they are needed. This is where we get to the meat of the class and how to prepare queries and execute them.

	/**
	 * Prepares a SQL query for safe execution.  Uses sprintf()-like syntax.
	 *
	 * This function only supports a small subset of the sprintf syntax; it only supports %d (decimal number), %s (string).
	 * Does not support sign, padding, alignment, width or precision specifiers.
	 * Does not support argument numbering/swapping.
	 *
	 * May be called like {@link http://php.net/sprintf sprintf()} or like {@link http://php.net/vsprintf vsprintf()}.
	 *
	 * Both %d and %s should be left unquoted in the query string.
	 *
	 * <code>
	 * wpdb::prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d", "foo", 1337 )
	 * </code>
	 *
	 * @link http://php.net/sprintf Description of syntax.
	 * @since 2.3.0
	 *
	 * @param string $query Query statement with sprintf()-like placeholders
	 * @param array|mixed $args The array of variables to substitute into the query's placeholders if being called like {@link http://php.net/vsprintf vsprintf()}, or the first variable to substitute into the query's placeholders if being called like {@link http://php.net/sprintf sprintf()}.
	 * @param mixed $args,... further variables to substitute into the query's placeholders if being called like {@link http://php.net/sprintf sprintf()}.
	 * @return null|string Sanitized query string
	 */
	function prepare($query = null) { // ( $query, *$args )
		if ( is_null( $query ) )
			return;
		$args = func_get_args();
		array_shift($args);
		// If args were passed as an array (as in vsprintf), move them up
		if ( isset($args[0]) && is_array($args[0]) )
			$args = $args[0];
		$query = str_replace("'%s'", '%s', $query); // in case someone mistakenly already singlequoted it
		$query = str_replace('"%s"', '%s', $query); // doublequote unquoting
		$query = str_replace('%s', "'%s'", $query); // quote the strings
		array_walk($args, array(&$this, 'escape_by_ref'));
		return @vsprintf($query, $args);
	}

The great thing about this class is that it has comments to show you exactly how to use the functions. Thank you WordPress!

This prepare function is INCREDIBLY important if you are allowing admins or guests to enter information. We want to make sure that no one is trying to SQL inject our database, so we use this function to “prepare” our queries. The comments give us this sample code: prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d", "foo", 1337 ) You will notice the query looking like a typical query, but the WHERE statement has column = %s and field = %d. These are place holders. %d stands for Decimal and %s stands for String. After the query, they give us the variables IN ORDER that the place holders were entered. “foo” corresponds with %s, and 1337 corresponds with %d. You can always enter a decimal as a string, but you can never enter a string as a decimal.

Again, this function simply ensures no one will create SQL injections, and possibly to ensure that it your queries are properly formatted. You don’t NEED to use prepare() for simple programmer controlled statements, but it is always recommended.

The following functions assist with error display:

	/**
	 * Print SQL/DB error.
	 *
	 * @since 0.71
	 * @global array $EZSQL_ERROR Stores error information of query and error string
	 *
	 * @param string $str The error to display
	 * @return bool False if the showing of errors is disabled.
	 */
	function print_error($str = '') {
		global $EZSQL_ERROR;
 
		if (!$str) $str = mysql_error($this->dbh);
		$EZSQL_ERROR[] = array ('query' => $this->last_query, 'error_str' => $str);
 
		if ( $this->suppress_errors )
			return false;
 
		if ( $caller = $this->get_caller() )
			$error_str = sprintf(/*WP_I18N_DB_QUERY_ERROR_FULL*/'WordPress database error %1$s for query %2$s made by %3$s'/*/WP_I18N_DB_QUERY_ERROR_FULL*/, $str, $this->last_query, $caller);
		else
			$error_str = sprintf(/*WP_I18N_DB_QUERY_ERROR*/'WordPress database error %1$s for query %2$s'/*/WP_I18N_DB_QUERY_ERROR*/, $str, $this->last_query);
 
		$log_error = true;
		if ( ! function_exists('error_log') )
			$log_error = false;
 
		$log_file = @ini_get('error_log');
		if ( !empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file) )
			$log_error = false;
 
		if ( $log_error )
			@error_log($error_str, 0);
 
		// Is error output turned on or not..
		if ( !$this->show_errors )
			return false;
 
		$str = htmlspecialchars($str, ENT_QUOTES);
		$query = htmlspecialchars($this->last_query, ENT_QUOTES);
 
		// If there is an error then take note of it
		print "<div id='error'>
		<p class='wpdberror'><strong>WordPress database error:</strong> [$str]<br />
		<code>$query</code></p>
		</div>";
	}
 
	/**
	 * Enables showing of database errors.
	 *
	 * This function should be used only to enable showing of errors.
	 * wpdb::hide_errors() should be used instead for hiding of errors. However,
	 * this function can be used to enable and disable showing of database
	 * errors.
	 *
	 * @since 0.71
	 *
	 * @param bool $show Whether to show or hide errors
	 * @return bool Old value for showing errors.
	 */
	function show_errors( $show = true ) {
		$errors = $this->show_errors;
		$this->show_errors = $show;
		return $errors;
	}
 
	/**
	 * Disables showing of database errors.
	 *
	 * @since 0.71
	 *
	 * @return bool Whether showing of errors was active or not
	 */
	function hide_errors() {
		$show = $this->show_errors;
		$this->show_errors = false;
		return $show;
	}
 
	/**
	 * Whether to suppress database errors.
	 *
	 * @param unknown_type $suppress
	 * @return unknown
	 */
	function suppress_errors( $suppress = true ) {
		$errors = $this->suppress_errors;
		$this->suppress_errors = $suppress;
		return $errors;
	}

By calling show/hide/suppress_errors it will trigger the error display. This is important because sometimes error display is great in debugging plug-ins, but when it is for public consumption, you may not want to display your connection information to the general public as it may be exploitable. Typically, I turn error display on during programming/debugging, but when I release something, I would like the error display tweaked or off so that it doesn’t mess up everything I have been working on.

The next lines “flush” the queries so that any queries in a queue to be queried are wiped out. That’s a lot of Q’s. Basically, it will make sure that only your queries that you desire are executed, so it can be good to do a “flush” before you start making queries.

	/**
	 * Kill cached query results.
	 *
	 * @since 0.71
	 */
	function flush() {
		$this->last_result = array();
		$this->col_info = null;
		$this->last_query = null;
	}

Pretty simple.

And finally we get to the “QUERY” function!

	/**
	 * Perform a MySQL database query, using current database connection.
	 *
	 * More information can be found on the codex page.
	 *
	 * @since 0.71
	 *
	 * @param string $query
	 * @return int|false Number of rows affected/selected or false on error
	 */
	function query($query) {
		if ( ! $this->ready )
			return false;
 
		// filter the query, if filters are available
		// NOTE: some queries are made before the plugins have been loaded, and thus cannot be filtered with this method
		if ( function_exists('apply_filters') )
			$query = apply_filters('query', $query);
 
		// initialise return
		$return_val = 0;
		$this->flush();
 
		// Log how the function was called
		$this->func_call = "\$db->query(\"$query\")";
 
		// Keep track of the last query for debug..
		$this->last_query = $query;
 
		// Perform the query via std mysql_query function..
		if ( defined('SAVEQUERIES') && SAVEQUERIES )
			$this->timer_start();
 
		$this->result = @mysql_query($query, $this->dbh);
		++$this->num_queries;
 
		if ( defined('SAVEQUERIES') && SAVEQUERIES )
			$this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() );
 
		// If there is an error then take note of it..
		if ( $this->last_error = mysql_error($this->dbh) ) {
			$this->print_error();
			return false;
		}
 
		if ( preg_match("/^\\s*(insert|delete|update|replace|alter) /i",$query) ) {
			$this->rows_affected = mysql_affected_rows($this->dbh);
			// Take note of the insert_id
			if ( preg_match("/^\\s*(insert|replace) /i",$query) ) {
				$this->insert_id = mysql_insert_id($this->dbh);
			}
			// Return number of rows affected
			$return_val = $this->rows_affected;
		} else {
			$i = 0;
			while ($i < @mysql_num_fields($this->result)) {
				$this->col_info[$i] = @mysql_fetch_field($this->result);
				$i++;
			}
			$num_rows = 0;
			while ( $row = @mysql_fetch_object($this->result) ) {
				$this->last_result[$num_rows] = $row;
				$num_rows++;
			}
 
			@mysql_free_result($this->result);
 
			// Log number of rows the query returned
			$this->num_rows = $num_rows;
 
			// Return number of rows selected
			$return_val = $this->num_rows;
		}
 
		return $return_val;
	}

Simply stated, this will execute any query you have, AND do a flush before it executes your query, so you don’t need to manually do one. The result that it returns is the number of rows affected by the query, so this is perfect if you are trying to count rows of a particular query. We will do a lot of sample code at the end to go over how to do a query.

The next function inserts a new row into a table, so you don’t have to use the “query” function yourself:

	/**
	 * Insert a row into a table.
	 *
	 * <code>
	 * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) )
	 * </code>
	 *
	 * @since 2.5.0
	 * @see wpdb::prepare()
	 *
	 * @param string $table table name
	 * @param array $data Data to insert (in column => value pairs).  Both $data columns and $data values should be "raw" (neither should be SQL escaped).
	 * @param array|string $format (optional) An array of formats to be mapped to each of the value in $data.  If string, that format will be used for all of the values in $data.  A format is one of '%d', '%s' (decimal number, string).  If omitted, all values in $data will be treated as strings.
	 * @return int|false The number of rows inserted, or false on error.
	 */
	function insert($table, $data, $format = null) {
		$formats = $format = (array) $format;
		$fields = array_keys($data);
		$formatted_fields = array();
		foreach ( $fields as $field ) {
			if ( !empty($format) )
				$form = ( $form = array_shift($formats) ) ? $form : $format[0];
			elseif ( isset($this->field_types[$field]) )
				$form = $this->field_types[$field];
			else
				$form = '%s';
			$formatted_fields[] = $form;
		}
		$sql = "INSERT INTO `$table` (`" . implode( '`,`', $fields ) . "`) VALUES ('" . implode( "','", $formatted_fields ) . "')";
		return $this->query( $this->prepare( $sql, $data) );
	}

Simply put, you can insert rows much easier with this function than by creating your own query. All that is required is the table name, the data, and the types. wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) ) shows us that the table name is ‘table’ in this example. The next variable is an associative array with the data to be entered. ‘column’ is the name of the field, and ‘foo’ is the data to be entered. ‘field’ is another field with 1337 to be entered under that field. The types, like explained earlier designated whether or not it is a string or decimal. So the first value in the associative array is ‘foo’, so the first value in the types array will be ‘%s’ designating it as a string. Pretty easy, and it will prepare the data for you too!

The next function is the Update function, and is very easy to manipulate:

	/**
	 * Update a row in the table
	 *
	 * <code>
	 * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( 'ID' => 1 ), array( '%s', '%d' ), array( '%d' ) )
	 * </code>
	 *
	 * @since 2.5.0
	 * @see wpdb::prepare()
	 *
	 * @param string $table table name
	 * @param array $data Data to update (in column => value pairs).  Both $data columns and $data values should be "raw" (neither should be SQL escaped).
	 * @param array $where A named array of WHERE clauses (in column => value pairs).  Multiple clauses will be joined with ANDs.  Both $where columns and $where values should be "raw".
	 * @param array|string $format (optional) An array of formats to be mapped to each of the values in $data.  If string, that format will be used for all of the values in $data.  A format is one of '%d', '%s' (decimal number, string).  If omitted, all values in $data will be treated as strings.
	 * @param array|string $format_where (optional) An array of formats to be mapped to each of the values in $where.  If string, that format will be used for all of  the items in $where.  A format is one of '%d', '%s' (decimal number, string).  If omitted, all values in $where will be treated as strings.
	 * @return int|false The number of rows updated, or false on error.
	 */
	function update($table, $data, $where, $format = null, $where_format = null) {
		if ( !is_array( $where ) )
			return false;
 
		$formats = $format = (array) $format;
		$bits = $wheres = array();
		foreach ( (array) array_keys($data) as $field ) {
			if ( !empty($format) )
				$form = ( $form = array_shift($formats) ) ? $form : $format[0];
			elseif ( isset($this->field_types[$field]) )
				$form = $this->field_types[$field];
			else
				$form = '%s';
			$bits[] = "`$field` = {$form}";
		}
 
		$where_formats = $where_format = (array) $where_format;
		foreach ( (array) array_keys($where) as $field ) {
			if ( !empty($where_format) )
				$form = ( $form = array_shift($where_formats) ) ? $form : $where_format[0];
			elseif ( isset($this->field_types[$field]) )
				$form = $this->field_types[$field];
			else
				$form = '%s';
			$wheres[] = "`$field` = {$form}";
		}
 
		$sql = "UPDATE `$table` SET " . implode( ', ', $bits ) . ' WHERE ' . implode( ' AND ', $wheres );
		return $this->query( $this->prepare( $sql, array_merge(array_values($data), array_values($where))) );
	}

Again the comments give us an example on how to use it. wpdb::update( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( 'ID' => 1 ), array( '%s', '%d' ), array( '%d' ) ) So the first value is the table name. The second variable is an array with the information you want to change. So we want to change the ‘column’ to be ‘foo’ and ‘field’ to be 1337. The next variable is the WHERE array, so in this case, WHERE ID = 1. You can add as many options as necessary to specify exactly which row is being used. The next variable is a types array that pertains to the updated info. %s goes with ‘foo’ and %d goes with 1337. The next variable is a types array that corresponds with the WHERE statement, so 1 is a decimal (%d). Its that simple!

This next function allows a use to take a SINGLE variable from a MySQL table.

	/**
	 * Retrieve one variable from the database.
	 *
	 * Executes a SQL query and returns the value from the SQL result.
	 * If the SQL result contains more than one column and/or more than one row, this function returns the value in the column and row specified.
	 * If $query is null, this function returns the value in the specified column and row from the previous SQL result.
	 *
	 * @since 0.71
	 *
	 * @param string|null $query SQL query.  If null, use the result from the previous query.
	 * @param int $x (optional) Column of value to return.  Indexed from 0.
	 * @param int $y (optional) Row of value to return.  Indexed from 0.
	 * @return string Database query result
	 */
	function get_var($query=null, $x = 0, $y = 0) {
		$this->func_call = "\$db->get_var(\"$query\",$x,$y)";
		if ( $query )
			$this->query($query);
 
		// Extract var out of cached results based x,y vals
		if ( !empty( $this->last_result[$y] ) ) {
			$values = array_values(get_object_vars($this->last_result[$y]));
		}
 
		// If there is a value return it else return null
		return (isset($values[$x]) && $values[$x]!=='') ? $values[$x] : null;
	}

You can do it through a query, or even specify the number of the row/column as $x and $y to pull specific data from. This is an awesome way to pull data if you have a static table that you draw data from.

Finally we get to retrieving data, in specific, a single row:

/**
	 * Retrieve one row from the database.
	 *
	 * Executes a SQL query and returns the row from the SQL result.
	 *
	 * @since 0.71
	 *
	 * @param string|null $query SQL query.
	 * @param string $output (optional) one of ARRAY_A | ARRAY_N | OBJECT constants.  Return an associative array (column => value, ...), a numerically indexed array (0 => value, ...) or an object ( ->column = value ), respectively.
	 * @param int $y (optional) Row to return.  Indexed from 0.
	 * @return mixed Database query result in format specifed by $output
	 */
	function get_row($query = null, $output = OBJECT, $y = 0) {
		$this->func_call = "\$db->get_row(\"$query\",$output,$y)";
		if ( $query )
			$this->query($query);
		else
			return null;
 
		if ( !isset($this->last_result[$y]) )
			return null;
 
		if ( $output == OBJECT ) {
			return $this->last_result[$y] ? $this->last_result[$y] : null;
		} elseif ( $output == ARRAY_A ) {
			return $this->last_result[$y] ? get_object_vars($this->last_result[$y]) : null;
		} elseif ( $output == ARRAY_N ) {
			return $this->last_result[$y] ? array_values(get_object_vars($this->last_result[$y])) : null;
		} else {
			$this->print_error(/*WP_I18N_DB_GETROW_ERROR*/" \$db->get_row(string query, output type, int offset) -- Output type must be one of: OBJECT, ARRAY_A, ARRAY_N"/*/WP_I18N_DB_GETROW_ERROR*/);
		}
	}

So this will return a single row from a query, hopefully a prepared query. Here is where you have to define whether or not you are getting an array back or an object by using those defines that we covered at the very first of this tutorial. I typically use ARRAY_A as that is how I have learned MySQL, but you can always keep it as an OBJECT if you would like. This would be an example of the code: $row = $mydb->get_row($mydb->prepare("SELECT * FROM Users WHERE ID = %d",$_GET['id']),ARRAY_A); I hope that is self explanatory for now.

Our next function grabs all the data from one column, like a list of links, or user names, or anything else where you just need a list of one column of data.

	/**
	 * Retrieve one column from the database.
	 *
	 * Executes a SQL query and returns the column from the SQL result.
	 * If the SQL result contains more than one column, this function returns the column specified.
	 * If $query is null, this function returns the specified column from the previous SQL result.
	 *
	 * @since 0.71
	 *
	 * @param string|null $query SQL query.  If null, use the result from the previous query.
	 * @param int $x Column to return.  Indexed from 0.
	 * @return array Database query result.  Array indexed from 0 by SQL result row number.
	 */
	function get_col($query = null , $x = 0) {
		if ( $query )
			$this->query($query);
 
		$new_array = array();
		// Extract the column values
		for ( $i=0; $i < count($this->last_result); $i++ ) {
			$new_array[$i] = $this->get_var(null, $x, $i);
		}
		return $new_array;
	}

The only data needed is a query, or the number of the row, and the end result will be an array with all the data. Very simple.

Following this, we have the function to get ALL the results from an SQL query:

	/**
	 * Retrieve an entire SQL result set from the database (i.e., many rows)
	 *
	 * Executes a SQL query and returns the entire SQL result.
	 *
	 * @since 0.71
	 *
	 * @param string $query SQL query.
	 * @param string $output (optional) ane of ARRAY_A | ARRAY_N | OBJECT | OBJECT_K constants.  With one of the first three, return an array of rows indexed from 0 by SQL result row number.  Each row is an associative array (column => value, ...), a numerically indexed array (0 => value, ...), or an object. ( ->column = value ), respectively.  With OBJECT_K, return an associative array of row objects keyed by the value of each row's first column's value.  Duplicate keys are discarded.
	 * @return mixed Database query results
	 */
	function get_results($query = null, $output = OBJECT) {
		$this->func_call = "\$db->get_results(\"$query\", $output)";
 
		if ( $query )
			$this->query($query);
		else
			return null;
 
		if ( $output == OBJECT ) {
			// Return an integer-keyed array of row objects
			return $this->last_result;
		} elseif ( $output == OBJECT_K ) {
			// Return an array of row objects with keys from column 1
			// (Duplicates are discarded)
			foreach ( $this->last_result as $row ) {
				$key = array_shift( get_object_vars( $row ) );
				if ( !isset( $new_array[ $key ] ) )
					$new_array[ $key ] = $row;
			}
			return $new_array;
		} elseif ( $output == ARRAY_A || $output == ARRAY_N ) {
			// Return an integer-keyed array of...
			if ( $this->last_result ) {
				$i = 0;
				foreach( (array) $this->last_result as $row ) {
					if ( $output == ARRAY_N ) {
						// ...integer-keyed row arrays
						$new_array[$i] = array_values( get_object_vars( $row ) );
					} else {
						// ...column name-keyed row arrays
						$new_array[$i] = get_object_vars( $row );
					}
					++$i;
				}
				return $new_array;
			}
		}
	}

Simply give the query, and then specify the way you want to receive the data (an array or object) using the defines discussed in the beginning. Then you can loop through all the results and display the data as you would like.

Finally, we will list the remaining functions and briefly describe what they do as they are not as popular as the preceding ones, and will rarely be used.

	/**
	 * Retrieve column metadata from the last query.
	 *
	 * @since 0.71
	 *
	 * @param string $info_type one of name, table, def, max_length, not_null, primary_key, multiple_key, unique_key, numeric, blob, type, unsigned, zerofill
	 * @param int $col_offset 0: col name. 1: which table the col's in. 2: col's max length. 3: if the col is numeric. 4: col's type
	 * @return mixed Column Results
	 */
	function get_col_info($info_type = 'name', $col_offset = -1) {
		if ( $this->col_info ) {
			if ( $col_offset == -1 ) {
				$i = 0;
				foreach( (array) $this->col_info as $col ) {
					$new_array[$i] = $col->{$info_type};
					$i++;
				}
				return $new_array;
			} else {
				return $this->col_info[$col_offset]->{$info_type};
			}
		}
	}
 
	/**
	 * Starts the timer, for debugging purposes.
	 *
	 * @since 1.5.0
	 *
	 * @return true
	 */
	function timer_start() {
		$mtime = microtime();
		$mtime = explode(' ', $mtime);
		$this->time_start = $mtime[1] + $mtime[0];
		return true;
	}
 
	/**
	 * Stops the debugging timer.
	 *
	 * @since 1.5.0
	 *
	 * @return int Total time spent on the query, in milliseconds
	 */
	function timer_stop() {
		$mtime = microtime();
		$mtime = explode(' ', $mtime);
		$time_end = $mtime[1] + $mtime[0];
		$time_total = $time_end - $this->time_start;
		return $time_total;
	}
 
	/**
	 * Wraps errors in a nice header and footer and dies.
	 *
	 * Will not die if wpdb::$show_errors is true
	 *
	 * @since 1.5.0
	 *
	 * @param string $message
	 * @return false|void
	 */
	function bail($message) {
		if ( !$this->show_errors ) {
			if ( class_exists('WP_Error') )
				$this->error = new WP_Error('500', $message);
			else
				$this->error = $message;
			return false;
		}
		wp_die($message);
	}
 
	/**
	 * Whether or not MySQL database is at least the required minimum version.
	 *
	 * @since 2.5.0
	 * @uses $wp_version
	 *
	 * @return WP_Error
	 */
	function check_database_version()
	{
		global $wp_version;
		// Make sure the server has MySQL 4.0
		if ( version_compare($this->db_version(), '4.0.0', '<') )
			return new WP_Error('database_version',sprintf(__('<strong>ERROR</strong>: WordPress %s requires MySQL 4.0.0 or higher'), $wp_version));
	}
 
	/**
	 * Whether of not the database supports collation.
	 *
	 * Called when WordPress is generating the table scheme.
	 *
	 * @since 2.5.0
	 *
	 * @return bool True if collation is supported, false if version does not
	 */
	function supports_collation()
	{
		return $this->has_cap( 'collation' );
	}
 
	/**
	 * Generic function to determine if a database supports a particular feature
	 * @param string $db_cap the feature
	 * @param false|string|resource $dbh_or_table (not implemented) Which database to test.  False = the currently selected database, string = the database containing the specified table, resource = the database corresponding to the specified mysql resource.
	 * @return bool
	 */
	function has_cap( $db_cap ) {
		$version = $this->db_version();
 
		switch ( strtolower( $db_cap ) ) :
		case 'collation' :    // @since 2.5.0
		case 'group_concat' : // @since 2.7
		case 'subqueries' :   // @since 2.7
			return version_compare($version, '4.1', '>=');
			break;
		endswitch;
 
		return false;
	}
 
	/**
	 * Retrieve the name of the function that called wpdb.
	 *
	 * Requires PHP 4.3 and searches up the list of functions until it reaches
	 * the one that would most logically had called this method.
	 *
	 * @since 2.5.0
	 *
	 * @return string The name of the calling function
	 */
	function get_caller() {
		// requires PHP 4.3+
		if ( !is_callable('debug_backtrace') )
			return '';
 
		$bt = debug_backtrace();
		$caller = array();
 
		$bt = array_reverse( $bt );
		foreach ( (array) $bt as $call ) {
			if ( @$call['class'] == __CLASS__ )
				continue;
			$function = $call['function'];
			if ( isset( $call['class'] ) )
				$function = $call['class'] . "->$function";
			$caller[] = $function;
		}
		$caller = join( ', ', $caller );
 
		return $caller;
	}
 
	/**
	 * The database version number
	 * @param false|string|resource $dbh_or_table (not implemented) Which database to test.  False = the currently selected database, string = the database containing the specified table, resource = the database corresponding to the specified mysql resource.
	 * @return false|string false on failure, version number on success
	 */
	function db_version() {
		return preg_replace('/[^0-9.].*/', '', mysql_get_server_info( $this->dbh ));
	}
}

get_col_info() will return info about that column, like the variable type, whether it is auto-increment, what the default value is, etc.

The timer_start and stop functions can be used to pinpoint when the error is occurring, and help in debugging your script.

bail() will basically show the errors that occurred in the MySQL query, or connection, and if enabled, will kill the script at that point. Also useful for debugging.

check_database_version(), supports_collation(), and has_cap() are all functions that ensure that the database will properly support the data that is entered, and is not something that you will need to use if you have already installed WordPress.

get_caller() is a neat function that will get the name of the function that created the wpdb object. It can be useful if you want to tweak your connection a little or run a specific script if it was opened in a certain function.

db_version() simply tells you the version of your MySQL database.

The remained of the code will initiate a database connection based on the config variables set during installation that will be used the remainder of the script to display all your WordPress info.

So lets go over some sample code using this. If you carefully read through my descriptions and are already familiar with MySQL then this will seem a little redundant. Lets create a generic page.

<?php
include("wp-includes/wp-db.php");
//automatically the connection is created
//we do not need to call the class using 
//$wpdb = new wpdb(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
$rows=$wpdb->get_results("SELECT * FROM wp_users", ARRAY_A);
//Now $rows is an array with a list of all registered users.
foreach($rows as $row){
   if($row['user_nicename']=='pyr0t3chnician')
   {
      echo "Admin ID/email is: ".$row['ID']." / ".$row['user_email'];
      $wpdb->update('wp_users', array ('user_email'=>'pyr0t3chnician@gmail.com'), array ('ID'=>1, 'user_nicename'=>'pyr0t3chnician'), array ('%s'), array ('%d','%s'));
      echo "<br>";
      echo "pyr0t3chnician's email should now be 'pyr0t3chnician@gmail.com'";
   }
}
$row2=$wpdb->get_row("SELECT * FROM wp_users WHERE ID='1' AND user_nicename='pyr0t3chnician'", ARRAY_A);
echo "<br>";
echo "pyr0t3chnician's new email is '$row2[user_email]'";
?>

There you have it, the most common way to use this class. This is how WordPress plug-ins use it. I am more than willing to answer any and all questions about this class to the best of my ability. I am not giving a tutorial about writing a plug-in just yet, but knowing this information, you can figure it out by looking at other help sites on the internet. Thanks! Leave me some feedback!