1

I am trying to extend the PDO class as well as turn it into a singleton. The only problem is that PDO's constructor is public, and PHP will not let me override it as a protected method. Is there any imaginative way around this? Will I be stuck with that loose end forever if I attempt this? An alternative may be not to extend PDO, but rather hold it in a static property, and do operations with it, but I wanted my class to retain all of the functionality of PDO if possible.

Jon
  • 428,835
  • 81
  • 738
  • 806
dqhendricks
  • 19,030
  • 11
  • 50
  • 83
  • Take a look at my answer to [this question](http://stackoverflow.com/q/5446835/50079), which was pretty much about the same problem as you are facing. – Jon Mar 27 '11 at 12:56

2 Answers2

1

You can just wrap the PDO class in your own "Singleton Factory" object. Basically, you implement your own singleton that contains a (single) PDO instance. (Note that I don't know PHP syntax so this is Java, but you should be able to get the idea)

MySingletonFactory.getInstance().getPDO();

A more verbose explaination can be found here: http://www.wikijava.org/wiki/Singleton_Factory_patterns_example

(Again, Java ... sorry - but I believe it'll get you where you where you want to go)

Brian Roach
  • 76,169
  • 12
  • 136
  • 161
  • This is great, and has me thinking, but the only problem is that I also want to modify the PDO class in other ways (adding methods). I suppose I could extend PDO to add the methods, then create a singleton factor class for that extended class however. – dqhendricks Mar 27 '11 at 07:54
1

Try this:

class MyPdoSingleton {

    protected $pdo;

    // Your own constructor called the first time if the singleton
    // instance does not exist
    protected function __construct() {
    }

    // Always returns the same instance (singleton)
    public static function getInstance() {
        static $instance;
        return (is_object($instance)) ? $instance : $instance = new self();
    }

    // Redirect any non static methods calls made to this class to the contained
    // PDO object.
    public function __call($method, $args) {
        return call_user_func_array(array($this->pdo, $method), $args);
    }

    // 5.3+
    public function __callStatic($method, $args) {
        $inst = self::getInstance();
        return call_user_func_array(array($inst, $method), $args);
    }

    // Or if you intend to have other classes inherit from this one
    /*public function __callStatic($method, $args) {
        $class = get_called_class();
        $inst = call_user_func(array($class, 'getInstance'));
        return call_user_func_array(array($inst, $method), $args);
    }*/

    public function myOtherMethod($arg) {
         // __call would not get called when requesting this method
    }
}

// Pre 5.3 use
$db = MyPdoSingleton::getInstance();
$db->myOtherMethod();

// Post 5.3 use
MyPdoSingleton::myOtherMethod();

Ops. I totally messed that up. That's what I get for answering questions first thing in a morning.

James
  • 2,609
  • 3
  • 20
  • 27
  • hmm. also an interesting idea. use magic method __call to call other methods on the contained pdo object. now i have some decisions to make. – dqhendricks Mar 27 '11 at 08:38
  • If your using 5.3 you can also use the static call magic method so that you don't have to call the getInstance all the time. In essence you would have static methods that worked in a non static context. – James Mar 27 '11 at 12:46
  • I realised after writing my last comment that it wasn't very well written to explain what I mean I have extended my example class, added comment and added use case examples. – James Mar 27 '11 at 12:54