You've done a good job with the title, however I choked at "I have a class Db
that extends MySQLi
". I've already explained in some detail why this is a terrible idea here so please don't, then you don't ever have to worry about this issue.
What's even more troubling is that you're trying to create a singleton child, out of a non-singleton parent. This indeed requires a private (or at least protected) constructor, but because the parent's constructor is public you can't have an overriding constructor that employs a more strict access modifier. This is a breach of contract and goes agains all rules/conventions and widely accepted "good" practices
Read about the SOLID principles, please
Another issue with your snippet is one of ambiguity:
self::$instance::parent::query($sql);
Now, within the child class, it may seem logical, and a valid use of the parent
keyword, but let's add this one line:
self::$instance = new OtherClass();
self::$instance::parent::query($sql);
In this case parent
might be a class constant (they're only upper-case by convention, it's not a requirement!). PHP not being strong typed, you can't just assume the given variable will always be of the same type, now can you?
If you want the query
method to be readily available to you on the child class, then just don't override it:
$evil = Db::getInstance($constructor_args);
$evil->query();//defaults to parent::query, if it's not overriden in the child class.
As an asside:
You shouldn't use a singleton in PHP
No, really, Honestly and truthfuly. Don't. Again, I've been quite verbose on that matter, too. Read my answer there please. It explains why you shouldn't use a singleton.
Besides, in your case, owing to my passionate loathing of the singleton pattern in PHP, I'd just create my own instance of PDO or MySQLi, thus bypassing your singleton-child-class, and set about making my life easier, and my code more testable anyway. Stop what you're doing: it's a waste of time!
Singletons are just globals in drag in PHP, because they are (by the very nature of the language) incapable of holding state in between requests. If you don't want 2 instances, don't create a second instance in the first place.
Singletons and gay marriage have something in common, in a weird way:
If you don't like gay marriage, that's your problem, not theirs. How can you avoid their marrying affect you? Two options:
- prohibit them from marrying (absolute, imperative approach, dictatorship-style)
- Don't marry a gay person (personal responsibility, live and let live, flexible-style)
Same applies to singletons: If you don't want there to be more than 1 connection to the DB, 2 options:
- Create a singleton (absolute, imperative approach, dictatorship-style)
- Don't connect to the DB a second time (personal responsibility, flexible)
Which of the two options seems the most reasonable?
Note: In case the analogy I made above offended anyone: That wasn't my intention, I simply tried to make a point.
As an asside (and waaay off-topic): if the preferable approach to both questions is, in your opinion, not the same in both cases, feel free to think that, that's your prerogative, but feel free to keep that to yourself, too. :)