Introduction:
The goal of this tutorial is to design a Data Abstraction Layer (DAL) in PHP, that will allow us to ignore the intricacies of MySQL and focus our attention on our Application Layer and Business Logic. Hopefully, by the end of this guide, you will have a working DAL and learn a little about PHP, MySQL, and Object-Oriented design in the process.
Assumptions:
You know PHP and have is set up.
You know MySQL and have it set up.
You have a cursory knowledge of object-oriented methodologies.
You are not a smacktard.
Defining the Project:
The purpose of this project is to create a working MySQL DAL to distance ourselves from the menial tasks that are associated with PHP/MySQL systems, such as passing around connection handles and iterating through result sets. We will create an object which will create and maintain our connection to our database, provide us with the tools necessary to perform all of our required SQL queries, properly handle errors, tidily present our data, and keep our application code clean.
Defining the Object:
Our Database object will consist of local variables, a constructor, mutators, and methods. I will leave out destructor and scoping from the database class, in order to maintain compatibility with PHP4.
Local Variables:
We will need variables to keep track of our connection information, as well as keep track of any open connections we may have.
The Constructor:
The Constructor for our class will server to create an instance of our Database class. It will provide the class' variables with their initial values.
The Mutators:
Our class will provide the functionality for changing databases on the fly, therefor we will design it to allow us to alter our connection information, both individually, and as a whole.
The Methods:
We are designing our DAL to connect to a database, therefor our Database class better have a connect method! Along with connect method, it should have a way of disconnecting, performing queries, and returning results.
Object Parts:
Our Database class wills start off simple enough; we need only to define the class and our variables to get the ball rolling:
Expand|Select|Wrap|Line Numbers
- class Database
- {
- var $database_name;
- var $database_user;
- var $database_pass;
- var $database_host;
- var $database_link;
Expand|Select|Wrap|Line Numbers
- function Database()
- {
- $this->database_user = "motoma";
- $this->database_pass = "bI1dU5";
- $this->database_host = "localhost";
- $this->database_name = "dalDatabase";
- }
Now we move on to our mutators. These will allow us fine-tuned control over our connection data. We will want one method for each variable we want to set. We could also, optionally, create one to set all in one call:
Expand|Select|Wrap|Line Numbers
- function changeUser($user)
- {
- $this->database_user = $user;
- }
- function changePass($pass)
- {
- $this->database_pass = $pass;
- }
- function changeHost($host)
- {
- $this->database_host = $host;
- }
- function changeName($name)
- {
- $this->databse_name = $name;
- }
- function changeAll($user, $pass, $host, $name)
- {
- $this->database_user = $user;
- $this->database_pass = $pass;
- $this->database_host = $host;
- $this->database_name = $name;
- }
We are really on a roll now! On to our connection related methods. Our connect method will need to establish a connection using the credentials we provide, and let us know when connection errors occur:
Expand|Select|Wrap|Line Numbers
- function connect()
- {
- $this->database_link = mysql_connect($this->database_host, $this->database_user, $this->database_pass) or die("Could not make connection to MySQL");
- mysql_select_db($this->database_name) or die ("Could not open database: ". $this->database_name);
- }
Conversly, the disconnect method will close any connection our class has previously made:
Expand|Select|Wrap|Line Numbers
- function disconnect()
- {
- if(isset($this->database_link)) mysql_close($this->database_link);
- else mysql_close();
- }
That was not very dificult, was it? On to our methods. The first, and most basic thing we will need to do is perform a query which returns no results. DELETES, UPDATES, and INSERTS fall into this category of query. Before we can perform a query, however, we should check if the database connection has been established. If not, we will need to establish a connection before we perform our query:
Expand|Select|Wrap|Line Numbers
- function iquery($qry)
- {
- if(!isset($this->database_link)) $this->connect();
- $temp = mysql_query($qry, $this->database_link) or die("Error: ". mysql_error());
- }
Onto our first result returning query handler. Personally I like working with arrays. Associative arrays make sense when returning a result set, due to the structures in which we commonly see these results displayed. Much like our resultless query handler, we will need to check on our connection before we try anything. It will then perform the query, and iterate through the result set, placing it tidily in an associative array for us to work with.
Expand|Select|Wrap|Line Numbers
- function query($qry)
- {
- if(!isset($this->database_link)) $this->connect();
- $result = mysql_query($qry, $this->database_link) or die("Error: ". mysql_error());
- $returnArray = array();
- $i=0;
- while ($row = mysql_fetch_array($result, MYSQL_BOTH))
- if ($row)
- $returnArray[$i++]=$row;
- mysql_free_result($result);
- return $returnArray;
- }
- }
One could add a few more functions to this list, namely for returning the last inserted id of an auto_increment field and checking for table existence.
Using our DAL:
Now that we have a DAL, how do we use it? Here's an example:
Expand|Select|Wrap|Line Numbers
- <?php
- // Our Database Class
- include("lib/database.php");
- // Instantiate our Database Class
- $db = new Database();
- // Query!
- $resArr = $db->query("SELECT * FROM users WHERE userid != 1");
- // $resArr is now an associative array containing the entire result set
- // of the SQL query. We can now use and abuse this data as necessay.
- // In this hypothetical situation, I am returing all of the users in
- // my table except the Administrator
- echo '<table><tr><th>UserID</th><th>UserName</th>';
- echo '<th>RealName</th><th>Homepage</th></tr>';
- foreach($resArr as $user)
- {
- echo '<tr><td>'.$user['userid'].'</td><td>'.$user['username'].'</td>';
- echo '<td>'.$user['realname'].'</td><td>'.$user['homepage'].'</td></tr>';
- }
- echo "</table>";
- ?>
Wrap Up:
Hopefully this tutorial has shown you how to quickly and easily create a minimal Data Abstraction Layer for your web application. Having a DAL to work with allows us to focus on the Application and Business layers of our applications, without having to go through the monotony of data access.