-2

So I am in a big mess here. I can say that my questions are few. I tried to make a singleton pattern but it returns me two different objects. This is what I made (saw in another post) and tried to test it.

class Singleton
{
    private static $instance = [];
    public function __construct(){}
    public function __clone(){}
    public function __wakeup(){
        throw new Exception("Cannot unserialize singleton");
    }

    public static function getInstance()
    {
        $class = get_called_class();
        if(!isset(self::$instance[$class])){
            self::$instance[$class] = new static();
        }
        return self::$instance[$class];
    }
}

class Dog extends Singleton
{
    public $name;

    public function __construct($name)
    {
        $this->name = $name;
    }
}
$dog = new Dog("Jorko");
$dog2 = new Dog("Peshko");

echo $dog->name; // returns "Jorko"
echo $dog2->name; // returns "Pesho"

I thought the second object ($dog2) should not be created and I would get $dog again. And why are we creating empty __constructor in the class Singleton? Also, why are we using this get_called_class? I mean according to php manual Gets the name of the class the static method is called in.. That is what it returns but isn't new static. I thought that new static do the same thing. I am in a real mess. I searched around the web but can't get it clear in my head. Thank you a lot!

tereško
  • 58,060
  • 25
  • 98
  • 150
Toma Tomov
  • 1,476
  • 19
  • 55
  • 1
    shouldn't the `__construct()` be private to prevent calling it? – Jeff Aug 10 '17 at 18:50
  • If you say so :D I mean i still a newbie. Still don't know which is the right way. – Toma Tomov Aug 10 '17 at 18:52
  • 4
    you use getInstance() to fetch a singleton - not new. https://stackoverflow.com/questions/203336/creating-the-singleton-design-pattern-in-php5 – Mike B Aug 10 '17 at 18:56
  • 1
    Problem with getInstance() though is that it doesn't have the value for the constructor. – Nigel Ren Aug 10 '17 at 18:58
  • Yes i get an error `Missing argument 1` if i try `$dog = Dog::getInstance(); $dog2 = Dog::getInstance();`. How should i pass the `name`? – Toma Tomov Aug 10 '17 at 19:00
  • 1
    Here is a free hint: **stop using singleton anti-pattern**. – tereško Aug 10 '17 at 19:04
  • 1
    Take a look at http://www.phptherightway.com/pages/Design-Patterns.html#singleton, but even better, don't apply the pattern. – localheinz Aug 10 '17 at 20:24
  • Possible duplicate of [Creating the Singleton design pattern in PHP5](https://stackoverflow.com/questions/203336/creating-the-singleton-design-pattern-in-php5) – localheinz Aug 10 '17 at 20:26

1 Answers1

1

Actually this is not correct. To implement the singleton pattern correct the constructor has to be protected to prevent the creation of an object with the new operator. The magic methods __clone and __wakeup should be private to prevent cloning and unserializing of the object.

If you set the accessibility on these methods like i said, you can get an instance of the singleton object by using the static method getInstance() which is there for that very reason.

Tamali
  • 326
  • 2
  • 8
  • Yes it works fine now. But still got the `Missing argument 1` error. How should i pass the `name` of the dog to the `Dog` `__constructor`? I can pass it later like `$dog->name = "Jorko"` and singleton works. But is the right way? – Toma Tomov Aug 10 '17 at 19:09
  • You should set the attribute name to `private` and create a getter- and setter-method. This would be the cleanest way. `public function getName() { return $this->name; }` as a getter and `public function setName($name) { $this->name = $name }`as a setter. After getting the instance you can simply set the name via the setter. – Tamali Aug 10 '17 at 19:13