Continuing my journey into more advanced OO, I'm trying to come up with the best way of being able to create a class called database that can happily use the soon-to-be-deprecated mysql_ commands, the mysqli_ library, and perhaps further down the line, other flavours of database as well.
I'd like my calling code to look something like this, for simplicity:
$db = new database("MYSQL", $host,$user,$password,$databaseName);
$db->query("SELECT myField FROM myTable");
while ($ROW = $db->fetch_assoc($QRY)) {
echo $ROW['myField'] . "<br/>";
}
When instantiating the database object, thats the part where i'd hope to specify MYSQL, MYSQLI, MSSQL, or whatever I feel like adding later.
I appreciate I could achieve exactly what I want by implementing switch blocks in every method of database:
class database() {
function __construct($type,$host,$user,$password,$databaseName) {
$this->dbType = $type;
switch ($type) {
case "mysql":
mysql_dao::connect($host,$user,$password,$databaseName);
break;
case "mysqli":
mysqli_dao::connect($host,$user,$password,$databaseName);
break;
case "mssql":
mssql_dao::connect($host,$user,$password,$databaseName);
break;
//other cases
}
}
function query($SQL) {
switch ($this->dbType) {
case "mysql": mysql_dao::query($SQL); break;
case "mysqli": mysqli_dao::query($SQL); break;
case "mssql": mssql_dao::query($SQL); break;
}
}
function fetch_assoc($SQL) {
switch ($this->dbType) {
case "mysql": mysql_dao::fetch_assoc($SQL); break;
case "mysqli": mysqli_dao::fetch_assoc($SQL); break;
case "mssql": mssql_dao::fetch_assoc($SQL); break;
}
}
//other methods....
}
...But this seems incredibly messy. Every time a method of database was called, the code is checking what type it is and calling the method from a different object.
So my next solution was simply to omit database at all, and just use calling code that looks like this:
$db = new mysql_dao($host,$user,$password,$databaseName);
$db->query("SELECT myField FROM myTable");
while ($ROW = $db->fetch_assoc($QRY)) {
echo $ROW['myField'] . "<br/>";
}
...and so we just call the database access object for the type of database we're using, but I don't like that either, if I wanted to shift a whole project from mysql to mysqli, i'd have to seek out all of these object references and change them. Although this is fairly trivial in a modern PHP editor, it still doesn't feel like it should be the best way (i'm starting to get theoretical instead of practical, now!)
So finally, i'd hoped that I could build the database class with a single switch statement:
class database {
function __construct($type,$host,$user,$pass,$db) {
switch ($type) {
default:
case "MYSQL":
return new mysql_dao($host,$user,$pass,$db);
break;
case "MYSQLI":
return new mysqli_dao($host,$user,$pass,$db);
break;
case "MSSQL":
return new mssql_dao($host,$user,$pass,$db);
break;
}
}
}
... and then just implement an interface with all of the other methods being in the classes for the individual database types. Unfortunately this isn't working either because even though the constructor for database returns an instance of another object, I can't call database->query because the method doesn't exist in the database object.
As far as I could work out, extending database with mysql_dao / mysqli_dao etc. classes wasn't right either, since you have to call the extended class to use its methods, and I want to call the parent class but use the methods of the child class. So this suggests that database should extend the dao classes, but you can't have one child class with multiple potential parents (can you?)
To conclude - I am almost sure I am missing something, and that what I want to do should be both possible and quite straightforward, and I just haven't thought of the right way - can anyone give me a pointer?