0

Trying to use objects that extend singletone, but something I can't do. How to call method from extended class?

How to show 13 non 12 with singleton?

class SingletonTest
{
    protected static $_instance;

    private function __construct(){}

    private function __clone(){}

    public static function getInstance() {

        if (null === self::$_instance) {
            self::$_instance = new self();
        }

        return self::$_instance;
    }

    public function test2(){
        return 12;
    }
}


class ExtendSingleton extends SingletonTest
{
    public function test2() {
        return 13;
    }
}


$b = ExtendSingleton::getInstance();
echo $b->test2(); //12
SiJey
  • 169
  • 1
  • 4
  • 9
  • You make an object from `SingletonTest` and this class doesn't extend `ExtendSingleton` so you can't get `13`! – Rizier123 Dec 01 '14 at 19:29
  • So there is no way to extend singletone? – SiJey Dec 01 '14 at 19:36
  • Yes there is but you have to make an object of `ExtendSingleton` so form there you have access to the method's of `ExtendSingleton` and `SingletonTest` – Rizier123 Dec 01 '14 at 19:37
  • Just to clarify what the issue is, inside of `getInstance`, `self` is equal to `SingletonTest`, not `ExtendedSingleton`. So the instance you are getting is a new instance of `SingletonTest`, not what you were expecting. As bicccio is suggesting, you can use `get_called_class()` to get the name of the class calling the static method which would return your extended class. Else, you would need to do something like have any extending classes register it's name with the parent class. – Jonathan Kuhn Dec 01 '14 at 19:42
  • So @Shkarbatovdmitriy you want a single instance for the whole hierarchy? Sounds weird... – bicccio Dec 01 '14 at 20:32

5 Answers5

1
public static function getInstance()
{
    static $instances = array();

    $calledClass = get_called_class();

    if (!isset($instances[$calledClass]))
    {
        $instances[$calledClass] = new $calledClass();
    }

    return $instances[$calledClass];
}
bicccio
  • 384
  • 1
  • 19
  • get_called_class() is only in PHP >= 5.3 – bicccio Dec 01 '14 at 19:45
  • 1
    But there will be mor than one object. – SiJey Dec 01 '14 at 19:45
  • 1
    @ShkarbatovDmitriy The static instance property in the parent class will be global to all instances of the class, including sub-classes. That is how static works in php. You would have to move the instance variable to each sub-class if you wanted it to be sub-class specific or use some sort of array to store each sub-subclass instance variable. – Jonathan Kuhn Dec 01 '14 at 19:47
  • I know, but we check $instances[$calledClass] instance for called class, it will do new called class, for each one. A lot of obejcts for all that extend singletone not one. – SiJey Dec 01 '14 at 19:53
  • @ShkarbatovDmitriy I don't understand. Sounds like what you would really want/need is a factory, not a singleton. Even if that factory stores one instance of each class and instantiates on first call, returning that instance on subsequent calls. – Jonathan Kuhn Dec 01 '14 at 20:03
1

You will get what you want if you use static binding keyword "static" instead of "self"

class SingletonTest
{
    protected static $_instance;

    private function __construct(){}

    private function __clone(){}

    public static function getInstance() {

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

        return static::$_instance;
    }

    public function test2(){
        return 12;
    }
}


class ExtendSingleton extends SingletonTest
{
    public function test2() {
        return 13;
    }
}


$b = ExtendSingleton::getInstance();
echo $b->test2(); //13

$a = SingletonTest::getInstance();
echo $a->test2(); //13

exit;

But as You see in the above example this way a class which You will call first to "getInstance" will take place to store its instance in the $_instance field.

There is no way to create a base singleton class and inherit singleton behavior.

Chris
  • 1,574
  • 4
  • 16
  • 49
Jakub Filipczyk
  • 1,141
  • 8
  • 18
0

So this should work for you:

(So first normally functions are public so you can use them if you extend from another class! And the you have to make an object from ExtendSingleton not from SingletonTest since ExtendSingleton exdend's -> SingletonTest and not the other way.)

<?php

    class SingletonTest {

        protected static $_instance;

        public function __construct() {

        }

        public function __clone() {

        }

        public static function getInstance() {

            if (null === self::$_instance) {
                self::$_instance = new self();
            }

            return self::$_instance;
        }

        public function test2(){
            return 12;
        }
    }


    class ExtendSingleton extends SingletonTest {

        public function test2() {
            return 13;
        }

    }


    $b = new ExtendSingleton();
    echo $b->test2(); //13


?>

Output:

13
Rizier123
  • 58,877
  • 16
  • 101
  • 156
0

I've tested bicccio's solution and it works

class SingletonTest
{
    protected static $_instances = [];

    private function __construct(){}

    private function __clone(){}

    public static function getInstance()
    {
        $calledClass = get_called_class();

        if (!isset(self::$_instances[$calledClass]))
        {
            self::$_instances[$calledClass] = new $calledClass();
        }

        return self::$_instances[$calledClass];
    }

    public function test2(){
        return 12;
    }
}


class ExtendSingleton extends SingletonTest
{
    public function test2() {
        return 13;
    }
}


$b = ExtendSingleton::getInstance();
echo $b->test2(); //13

$a = SingletonTest::getInstance();
echo $a->test2(); //12
Jakub Filipczyk
  • 1,141
  • 8
  • 18
0

You can extend singleton class in php using late static binding the whole process is well discussed in this question.

Creating the Singleton design pattern in PHP5

Community
  • 1
  • 1