php_nub_qq
php_nub_qq

Reputation: 16065

Run parent non-static function from singleton child's instance property

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

Answers (1)

Elias Van Ootegem
Elias Van Ootegem

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:

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. :)

Upvotes: 2

Related Questions