Reputation: 16065
I honestly think I did a pretty awesome job at creating the most exhaustive title possible :D
.
I have a class Db
that extends MySQLi
. I have some stuff going on before executing queries, but to execute a query I need to call parent::query()
. The problem is that Db
is singleton and I don't really know how to do that..
$result = parent::query($sql);
This is what works if __construct
is public. As soon as I make it private I start getting a bunch of errors basically saying
Couldn't fetch db
In a desperate attempt I tried this, which didn't work
$result = self::$instance::parent::query($sql)
Can someone please tell me how I can do this?
Upvotes: 0
Views: 231
Reputation: 76408
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:
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:
Same applies to singletons: If you don't want there to be more than 1 connection to the DB, 2 options:
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. :)
Upvotes: 2