Andrew
Andrew

Reputation: 11

PHP Singleton Acting Funny

I have the following code:

$e1 = call_user_func(array("MySQL_Extension", "getInstance"));
$e2 = call_user_func(array("Error_Extension", "getInstance"));
self::$extensions->MySQL = $e1;
self::$extensions->Error = $e2;

// Debug
echo "<pre>";
print_r(self::$extensions);

Each getInstance() method looks like this:

public static function getInstance()
{
    if (self::$_instance == null)
    {
        self::$_instance = new self;
    }

    return self::$_instance;
}

Both classes extend the same "Extension_Abstract" class, but for some reason, the "print_r" debug statement listed outputs the following:

stdClass Object (
    [MySQL] => MySQL_Extension Object
    [Error] => MySQL_Extension Object
)

Do you all have any idea why it would be returning two "MySQL_Extension" objects, and completely ignoring the Error_Extension class? I'm so confused!

Upvotes: 1

Views: 173

Answers (5)

Ben Lee
Ben Lee

Reputation: 53319

See http://socket7.net/article/php-5-static-and-inheritance.

The problem is there is only one static variable, defined within the scope of the parent class. To create two static variables, the easiest way is to just define $_instance variable and get_instance method in both subclasses.

Another possible workaround is listed in the comments of the above article: "pass an extra class name parameter into the static method calls telling the method which class it should 'act as.'"

Upvotes: 2

Stan
Stan

Reputation: 1

late binding issue.

public static function getInstance()
{
    if (static::$_instance == null)
    {
        static::$_instance = new static();
    }

    return static::$_instance;
}

Upvotes: 0

brian_d
brian_d

Reputation: 11360

Try not using self::, but MySQL_Extension:: and Error_Extension:: explicitly.

Also, the abstract parent class Extension_Abstract should not contain the implementation for the getInstance method.

Upvotes: 0

Alnitak
Alnitak

Reputation: 339786

Is $_instance in the base class?

If so, then you've got a singleton for the entire hierarchy, not each specific subclass.

Upvotes: 0

ircmaxell
ircmaxell

Reputation: 165191

Since self is resolving to MySQL_Extension, I'm assuming that each class has this method (rather than being defined in Extension_Abstract. However, where is self::$_instance defined? My instinct is that it's defined on Extension_Abstract. Simply re-define it in each class (protected static $_instance = null;).

Also, instead of self, if you're using 5.3+ you should use static since it enables you to inherit and use late-static-binding to determine the class.

If that doesn't help, post more code (the class definitions would help)...

Upvotes: 1

Related Questions