TalkPHP
 
 
Account Login
Latest Articles
» The basic usage of PHPTAL, a XML/XHTML template library for PHP
» Vulnerable methods and the areas they are commonly trusted in.
» Simple way to protect a form from bot
» The Basics On: How Session Stealing Works
» How to keep your forms from double posting data
IRC Channel
IRC Speech Bubble Join the friendly bunch on IRC...
(#TalkPHP on Freenode)

...Also available via a web interface.

See this thread for information on the TalkPHP Free Hugs Initiative™. Subject to availability.
Associates
Associates
CSS Tutorials
Reply
 
LinkBack Thread Tools Search this Thread Display Modes
Old 05-30-2008, 08:08 PM   #1 (permalink)
is cute and cuddly
 
delayedinsanity's Avatar
 
Join Date: Mar 2008
Location: Vegas, Baby
Posts: 963
Thanks: 31
delayedinsanity is on a distinguished road
Default To abstract, or not to...

So I just ran into another snag. I've been developing a small group of classes that all use mysqli. After two weeks of work on my local test server, I uploaded them to my host to put em online to show off, and.... my host doesn't have mysqli, it's mysql or bust.

Not only do I hate them because for such a large company they barely offer more than a skeleton server, but I also hate them because they brought it to my attention that my scripts aren't very backwards compatible at all.

So now I want to create a very very basic abstraction. I'm thinking two classes, both sadly just reproducing the same methods the mysqli object uses, but one which would use mysql functions if that extension isn't loaded on the server. At first I thought this would be a good chance to play with abstract classes, but I dunno.

Any ideas for how to go about this? I basically want something in the background to check function_exists('mysqli') and use one of two possible sets of methods based on that knowledge. Maybe it'd just be easier to release two versions of this entire thing, one based on mysqli, one on mysql heh...
-m
delayedinsanity is offline  
Reply With Quote
Old 05-30-2008, 09:14 PM   #2 (permalink)
La Vida es Sueño
Advanced Programmer Top Contributor 
 
Wildhoney's Avatar
 
Join Date: Sep 2007
Location: Oldham
Posts: 2,267
Thanks: 90
Wildhoney is on a distinguished road
Default

The approach I would take would be something like the following. First I would create an interface to hold all the child class methods that I'll be needing for my database class:

php Code:
interface Database_Interface
{
    public function insertRow($aData);
    public function updateRow($aData, $iRowId);
    public function deleteRow($iRowId);
}

Then I would create the child classes, one for each single database type possible, which all implement that interface:

php Code:
class Database_PostgreSQL implements Database_Interface
{
    public function insertRow($aData) { return 'Insert PostgreSQL'; }
    public function updateRow($aData, $iRowId) { return 'Update PostgreSQL'; }
    public function deleteRow($iRowId) { return 'Delete PostgreSQL'; }
}

class Database_MySQL implements Database_Interface
{
    public function insertRow($aData) { return 'Insert MySQL'; }
    public function updateRow($aData, $iRowId) { return 'Update MySQL'; }
    public function deleteRow($iRowId) { return 'Delete MySQL'; }
}

class Database_MySQLi implements Database_Interface
{
    public function insertRow($aData) { return 'Insert MySQLi'; }
    public function updateRow($aData, $iRowId) { return 'Update MySQLi'; }
    public function deleteRow($iRowId) { return 'Delete MySQLi'; }
}

And finally add the database base which would be the class that's first initialised:

php Code:
class Database
{
    private $m_pDatabase;
   
    public function setDatabase(Database_Interface $pDatabase)
    {
        $this->m_pDatabase = $pDatabase;
    }
   
    public function insertRow($aData)
    {
        return $this->m_pDatabase->insertRow($aData);
    }
   
    public function updateRow($aData, $iRowId)
    {
        return $this->m_pDatabase->updateRow($aData, $iRowId);
    }
   
    public function deleteRow($iRowId)
    {
        return $this->m_pDatabase->deleteRow($iRowId);
    }
}

Then last of all we would initialise that class we've just created, and set the database we want to use by using the setDatabase function. By doing that, we can seamlessly change database types, as the majority of the code is kept in the child classes.

php Code:
$pDb = new Database();
$pDb->setDatabase(new Database_PostgreSQL());
echo $pDb->insertRow(array(1, 2));

As we have set the database type to PostgreSQL, any function calls will be routed to the PostgreSQL child class. Voila!
__________________
The man who comes back through the Door in the Wall will never be quite the same as the man who went out.

Last edited by Wildhoney : 05-31-2008 at 02:10 AM.
Send a message via AIM to Wildhoney Send a message via MSN to Wildhoney Send a message via Yahoo to Wildhoney
Wildhoney is offline  
Reply With Quote
The Following 3 Users Say Thank You to Wildhoney For This Useful Post:
coiyeun2b (06-29-2008), delayedinsanity (05-30-2008), maZtah (06-02-2008)
Old 05-30-2008, 11:03 PM   #3 (permalink)
is cute and cuddly
 
delayedinsanity's Avatar
 
Join Date: Mar 2008
Location: Vegas, Baby
Posts: 963
Thanks: 31
delayedinsanity is on a distinguished road
Default

That is definitely one of the most in depth answers I've gotten to one of my random scenarios, thank you.

I think I cornered myself away from the answer when the idea of an abstract class first struck me... I was pretty close to that answer, it just didn't seem right in my head, because I was picturing a relationship between two types of classes (the abstract, and it's children). It seemed like it should work, but I just kept snagging on some unknown feeling of not being quite right. Having an abstract/interface, children and a controller suddenly makes all the queasiness go away and that little light go *bing*.
-m
delayedinsanity is offline  
Reply With Quote
Old 06-01-2008, 12:15 AM   #4 (permalink)
La Vida es Sueño
Advanced Programmer Top Contributor 
 
Wildhoney's Avatar
 
Join Date: Sep 2007
Location: Oldham
Posts: 2,267
Thanks: 90
Wildhoney is on a distinguished road
Default

Pleasure !

In theory though you could go down the abstract path, with something like so:

php Code:
abstract class Database_Abstract
{
    abstract function insertRow($aData);
    abstract function updateRow($aData, $iRowId);
    abstract function deleteRow($iRowId);
   
    public function __construct()
    {
        printf("Connection established\n");
    }
}

class Database_MySQL extends Database_Abstract
{
    public function insertRow($aData) { return 'Insert MySQL'; }
    public function updateRow($aData, $iRowId) { return 'Update MySQL'; }
    public function deleteRow($iRowId) { return 'Delete MySQL'; }
}

$pDb = new Database_MySQL();
echo $pDb->insertRow(array(1, 2));

However, the reason I would take the former path, as aforesaid in my earlier post, is due to the logging and other centralised functionality that would be beneficial to the overall harmony of a database class. Whenever you make a call in the former, you can perform any generic tasks, such as logging, whereas if you take the latter route, with abstracts, you'll have to set-up logging in each individual child class, or at least call a function from the abstract.
__________________
The man who comes back through the Door in the Wall will never be quite the same as the man who went out.
Send a message via AIM to Wildhoney Send a message via MSN to Wildhoney Send a message via Yahoo to Wildhoney
Wildhoney is offline  
Reply With Quote
The Following User Says Thank You to Wildhoney For This Useful Post:
coiyeun2b (06-29-2008)
Old 06-29-2008, 02:18 AM   #5 (permalink)
The Prestige
Advanced Programmer Top Contributor Good Samaritan 
 
sketchMedia's Avatar
 
Join Date: Oct 2007
Location: Manchester, UK
Posts: 854
Thanks: 32
sketchMedia is on a distinguished road
Default

TalkPHP - Using Abstract Classes to Define Rules

TalkPHP - Working with Interfaces

may help.

An interface is a prototype/blueprint of an implemented class, in otherwords it defines rules that a class must implement and nothing else and they cant contain functioning code.

An abstract is like an interface but you can define some of it to be functional code that will be available to the derived class through inheritance.

So in short, abstracts are much like interfaces, but they allow you to have common methods inherited into derived objects, where as interfaces just enforce the API of the object.
__________________
mysql> SELECT * FROM `users` WHERE `users`.`clue` > 0;
Empty set (0.00 sec)
sketchMedia is offline  
Reply With Quote
The Following 2 Users Say Thank You to sketchMedia For This Useful Post:
coiyeun2b (06-30-2008), hello-world (02-27-2009)
Old 02-27-2009, 07:07 PM   #6 (permalink)
The Contributor
 
hello-world's Avatar
 
Join Date: Feb 2009
Posts: 73
Thanks: 30
hello-world is on a distinguished road
Default

Thanks SketchMedia.Today I was trying to learn Abstract class and methods from a book. I downloaded the from their website. It was giving me Error.
By read your Article.The error is solved And Saved me lots of time.
hello-world is offline  
Reply With Quote
Reply



Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


All times are GMT. The time now is 03:09 PM.

 
     

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.1.0
Inactive Reminders By Icora Web Design