ucantblamem

My name? Base… Data Base.

17th Oct 2006

I was approached a few weeks ago to be part of an exciting little project that unfortunately I’m not at liberty to reveal (for now, let’s refer to it as “project-n“) and therefore must digress on the details of what the app will do. However, the technical aspect of the project has been particularly interesting and lends itself to a post such as this.

The public-facing part of the site is/will-be a flash application displaying content in a “turn-page” fashion, which I will probably talk more on at a later time. This system will grab its’ data as XML output from a MySQL database.

On the back-end, we basically needed a CRUD (Create, Read, Update, Delete) style system, with some custom file management integrated into it. I had two major language choices: Ruby (with the Rails framework of course) or PHP. The programmer in me desperately wanted to take this opportunity to go nuts with Rails and create some great new web-two-point-o masterpiece, but the time limit we’re working with meant that I really needed to stick to PHP (which I am far more familiar with).

So, with language choice out of the way I figured I had better pick a nice little framework and get the job done simply and quickly. After a couple of hours spent looking at the various option available, I soon realised that using a framework is just like learning a new language as you have to go back and learn all the conventions etc… Not really ideal, as RoR would probably be quicker than learning a new PHP framework. SO, staring down the barrel of a VERY clean slate I looked at what I wanted to achieve and slowly pieced together an execution strategy.

Now, as a side-note it’s worth keeping in mind that last week I had a discussion with my boss regarding our ever increasing workload and we are definitely taking on an employee in the near future. However, considering our last struggle to find a PHP Developer who is familiar with the Joomla! Framework, it is just so much easier for us to find another designer while I slide into a development role. To be honest I have been getting a bit tired of design lately and have been doing a lot of development work anyway. So, it all just fits together like a glove and means that building my own framework for “project-n” is the perfect refresher course in PHP.

Phew… Now, with the intro out of the way, I wanted to cruise into some code. Obviously the first thing to do is put together a database API so that we can grab and manipulate data. A long time ago I put together a super basic connection management class and posted it on my old site, this was a good start. I have modified it slightly to be more extensible, but this makes up the basic part of our class:

class DB {
	var $host;
	var $user;
	var $pass;
	var $db;

	var $query;
	var $result;
	var $lastresult;
	var $rowsaffected;
	var $insertid;
	var $link;

	var $errors;

	function DB($host, $db, $user, $pass) {
		$this->host = $host;
		$this->db = $db;
		$this->user = $user;
		$this->pass = $pass;

		$this->DBconnect();
	}

	function DBconnect() {
		$this->link = @mysql_connect($this->host, $this->user, $this->pass);
		if(!$this->link) {
			// Error here
		}
		$this->select($this->db);
		register_shutdown_function(array(&$this, 'close'));
	}

	function select($db) {
		if (!@mysql_select_db($db, $this->link)) {
			// error here
		}
	}

	function close() {
		// Close our database connection
		// This is ultra important - don't wanna overload our server.
		@mysql_close($this->link);
	}
}

Very basically, when the class is initalised we make a connection to MySQL and tell it which database we want to look at. You’ll notice we’ve also registered a function to close the connection automatically for us when we’re done. We really need so much more functionality than this, so let’s get a mechanism for processing queries (the interesting part):

	function doquery() {
		$this->result = @mysql_query($this->query, $this->link);
		if(mysql_error()) {
			// error here
		}

		// We need to handle insert, delete, update
		// and replace statements differently to select statements:
		if(preg_match("/^\\s*(insert|delete|update|replace) /i",$this->query)) {
			$this->rowsaffected = mysql_affected_rows();
			// Just in case, let's grab the insertid - could be userful:
			if(preg_match("/^\\s*(insert|replace) /i",$this->query)) {
				$this->insertid = mysql_insert_id($this->link);
			}
			// How many did we successfully change?
			$return = $this->rowsaffected;
		} else {
			// How we handle select statements:
			$i = 0;
			while($row = @mysql_fetch_object($this->result)) {
				$this->lastresult[$i] = $row;
				$i++;
			}

			@mysql_free_result($this->result);

			// Store number of rows returned
			$this->numrows = $i;

			// Return number of rows selected
			$return = $this->numrows;
		}
		return $return;
	}

Okay, let’s give ourselves some ability to interface with this puppy hey?

	function setquery($query) {
		$this->query = $query;
	}

	function getresults() {
		// Run query and grab the return:
		$this->doquery();
		if($this->lastresult) {
			return $this->lastresult;
		}
		else {
			return false;
		}
	}

	function getaffectedrows($suppress=false) {
		if(!$suppress) {
			// Run the query by default
			// Otherwise JUST return the results:
			$this->doquery();
		}

		if($this->rowsaffected) {
			return $this->rowsaffected;
		} else {
			return false;
		}
	}

	function geterrormsg() {
		// Simple error return:
		return '[' . mysql_errno() . '] ' . mysql_error();
	}

The complete code can be grabbed here: database.class.phps

This code will no doubt be added to over the coming week or two, but in it’s current state we can simply use it like so:

$db = new DB( "localhost", "mytestdbname", "root", "root" );
$db->setquery("SELECT title FROM mytesttablename WHERE 1 = 1");
$resultsarray = $db->getresults();

Easy right? Obviously you just do a loop to output the array of objects like this:

foreach($resultsarray as $result) {
	echo $result->title . "<br />";
}

And that’s the end of the game ladies and gentlemen! Enjoy.

Leave a Reply