Error while implementing singleton pattern

I try to implement a singleton template and I get the following error

Fatal error: database access level :: __ construct () must be public (as in the PDO class) in /config/database.php on line 29

<?php class Database extends PDO { private static $instance; private function __construct() { return parent::__construct( "mysql:host=localhost;dbname=live", "root", "root" ); } public function getInstance() { if(self::$instance === null) { self::$instance = new Database(); } return self::$instance; } public function __clone() { die(__CLASS__ . ' class cant be instantiated. Please use the method called getInstance.'); } } $mySingleton = Database::getInstance(); var_dump($mySingleton); ?> 
+4
source share
5 answers

You cannot change the access level for the override method.

Instead of extending the PDO, you can simply have a PDO instance in the Database . Composition is more flexible than inheritance.

+3
source

Declaring __construct () function such as private as private function __construct() , you do not actually allow PHP will automatically call it when you create the object.

Instead, you should always have your __construct (), as well as other well-known magic methods declared.

 public function __construct() { // Now PHP can access me } 

As for your Database class to execute a singleton pattern, it makes no sense to extend a class that doesn't (i.e. PDO). Instead, do the following:

 <?php class Database { private static $instance; public function __construct() { // Check to see if static PDO instance // has already been created, so we create only one (singleton) if(!self::$instance) { self::$instance = new PDO( "mysql:host=localhost;dbname=live", "root", "root" ); } } public function getInstance() { if(self::$instance === null) { self::__construct(); } return self::$instance; } public function __clone() { die(__CLASS__ . ' class cant be instantiated. Please use the method called getInstance.'); } } $mySingleton = Database::getInstance(); var_dump($mySingleton); ?> 
+4
source

Since the PDO __construct() function is public, you cannot extend it with the private __construct() function.

Thus, a β€œreal” singleton is not possible.
You must set the public function __construct() .

+3
source

You must

1) disable the designer by setting it to closed.

2) create a single PDO object by calling only the static method. The static method should return an instance of the PDO.

In Silex or Symfony, you will need to assign the class name "\" or use "use \ PDO;". This does not mean that it is a global class.

Ps. if you set the __constructor to the public and use return functino, note that it will not throw any exceptions or warnings, but you will get the returned class object, not the actual value of the return statement.

So $ db = new Database () will return an object of class Database. Then from there you will need to access the PDO using the class method. $ pdo = $ db-> getInstance () This is the wrong way to create the correct singleton.

If you are interested in learning more about the pros and cons of singleton, and for some usage examples read this Best Practices in singleton PHP classes , you will find more information about this template.

 /** * Singleton pattern */ class Database { /** * holds the only PDO instance */ private static $_instance; /** * private __constructor not accesible */ private function __construct() { self::$instance = new PDO( "mysql:host=localhost;dbname=live", "root", "root" ); } /** * clone will not duplicate object */ public function __clone() { die(__CLASS__ . ' class cant be instantiated. Please use the method called getInstance.'); } /** * the only public function to access or create PDO object */ public static function getInstance() { if(!self::$_instance instanceof PDO){ new self; } return self::$_instance; } } 
0
source

The need to have a different level of access between parent and child constructors is excellent lecit , in addition to technical difficulties with the PHP source code.

In fact, it was reported as a bug ( # 61970 ).

In this commit made in March 2017, if I'm not mistaken, the developer says it was closed:
http://git.php.net/?p=php-src.git;a=commitdiff;h=5324fb1f348f5bc979d9b5f13ac74177b73f9bf7

I am using PHP 7.0.24, released in July, but I still see that it has not been fixed.

0
source

Source: https://habr.com/ru/post/1400851/


All Articles