This is something I've struggled with for some time now, and I know I'm not alone. I'm looking for a "best practice" way to be able to use a database connection in my PHP classes. I've just started to read about static functions and singletons. I currently think this is the way to go, but I want to avoid seeing every problem as a nail just after buying a new hammer, if you know what I mean. I know I'm not the only person to query this, but I can't find a good resource that explains how it should be done.
What I think I'm looking for is a re-useable class that removes, or minimises, any global calls. I know that I don't want to make multiple copies of a class or create multiple database instances for performance reasons.
What I think I've made (and I'm a little fuzzy on the definitions of some of the words) is a database singleton.
What I'm looking for is some advice. Is this how I "should" be using a database class? If so, have I written it in the best way?
Here's the PHP:
<?php
# set all errors and notices on.
error_reporting(E_ALL);
ini_set('display_errors', '1');
# database static class.
class database {
private static $connection;
private static $instance;
private function __construct(){
# run the connection here
self::$connection='*dbcon*';
echo 'connecting...<br />';
}
public static function getInstance(){
# this only runs once, calling the construct once.
if(!self::$instance){
self::$instance = new database();
}
return self::$instance;
}
private static function sanitise($data){
# sanitise data before it's sent to the database
return '~'.$data.'~';
# sanitisation is flagged by adding tildas to a string.
}
public function runquery($query){
echo 'running query...<br />';
return self::$connection.' - '.self::sanitise($query);
}
}
# user class
class myuser {
function getuser($username){
# this uses the database class, but shouldn't call a second copy of it.
# I should be able to re-use the connection string created outside this class.
# Doing so sould not trigger a reconnection (flagged by echoing 'connecting...')
echo database::runquery('SELECT * FROM user_tbl WHERE username='.$username);
# The above line will call everything I need to return a result including sanitisation.
}
}
# this line would be needed to substantiate an instance of the database.
database::getInstance();
# run two queries on the database to see if they both run from the same connection
echo database::runquery('test query');
echo '<br />';
echo database::runquery('second test query');
echo '<br />';
# substantiate a new user class
$user = new myuser();
# load in the current user.
$user->getuser('mark');
?>
And here's the results:
connecting...
running query...
*dbcon* - ~test query~
running query...
*dbcon* - ~second test query~
running query...
*dbcon* - ~SELECT * FROM user_tbl WHERE username=mark~
I only have one "connecting..." string in my output, and I can call a database query from anywhere without calling something like $this->database = new database();
in the constructor of each and every class I make.