22

This question may be really a silly question for many. But, i could not find the exact answer for it.

What is singleton class in PHP?

I went through many tutorials, still do not understand exact meaning of it. What I understand is that, it cannot be instantiated more than once. The object will be shared. What does that really mean? Suppose the singleton is implemented for database connection, does it mean, that if 'A' is access the site and logging in. Meanwhile say 'B' tries to login and B will not be able to login until A logout and releases the object?

Sivabalan
  • 971
  • 2
  • 18
  • 43
karthik_spain
  • 331
  • 1
  • 2
  • 8
  • 1
    Database connections is not a particularly good use case—I've written several applications that had to connect to two different database servers. And it isn't specifically a PHP concept: it's a OOP design pattern you can implement in any OOP language. – Álvaro González Jul 20 '14 at 15:44
  • 3
    Have you already read about the [*Singleton pattern* at Wikipedia](http://en.wikipedia.org/wiki/Singleton_pattern)? – Gumbo Jul 20 '14 at 15:45
  • A Singleton is one of the basic PHP design patterns, and although some take it as an antipattern, it can be used and evolved in a serie of possibilities: https://www.phpclasses.org/package/12016-PHP-Create-class-objects-in-a-limited-number-of-times.html – Carlos Matos Mar 25 '21 at 00:36
  • Singleton as described in most tutorials (and in the answers of this question) looks appealing but it proves to be a blocker on testing and other aspects of code maintenance. It also breaks the separation of concerns principle. Split the creation and maintenance of that unique instance from the behaviour specific to the component and you get two classes, each of them having a single responsibility. You can then test them, create two or more instances of the "singleton" class (in some projects you need two connections to the database, not only one) etc. – axiac Mar 06 '23 at 12:39

4 Answers4

42
  • Singleton can be used like a global variable.
  • It can have only one instance (object) of that class unlike normal class.
  • When we don't want to create a more than one instance of a class like database connection or utility library we would go for singleton pattern.
  • Singleton makes sure you would never have more than one instance of a class.
  • Make a construct method private to make a class Singleton.
  • If you don't want to instantiate a multiple copies of class but only one then you just put it in singleton pattern and you can just call methods of that class and that class will have only one copy of it in a memory even if you create another instance of it.
  • If user just wants to connect to database then no need to create a another instance again if the instance already exist, you can just consume first object and make the connection happen.

e.g.

<?php
    class DBConn {

        private static $obj;

        private final function  __construct() {
            echo __CLASS__ . " initializes only once\n";
        }

        public static function getConn() {
            if(!isset(self::$obj)) {
                self::$obj = new DBConn();
            }
            return self::$obj;
        }
    }

    $obj1 = DBConn::getConn();
    $obj2 = DBConn::getConn();
    
    var_dump($obj1 == $obj2);
?>

Output:

DBConn initializes only once
bool(true)

Object1 and Object2 will point to the same instance

            _______________________
           |                       |
$obj1 ---->|  Instance of DBConn   |<----- $obj2
           |_______________________| 
Dharman
  • 30,962
  • 25
  • 85
  • 135
Hemangi Gokhale
  • 700
  • 6
  • 11
25

A singleton is a particular kind of class that, as you correctly said, can be instantiated only once.

First point: it isn't a PHP related concept but an OOP concept.

What "instantiated only once means?" It simply means that if an object of that class was already instantiated, the system will return it instead of creating new one. Why? Because, sometimes, you need a "common" instance (global one) or because instantiating a "copy" of an already existent object is useless.

Let's consider for first case a framework: on bootstrap operation you need to instantiate an object but you can (you have to) share it with other that request for a framework bootstrap.

For the second case let's consider a class that has only methods and no members (so basically no internal state). Maybe you could implement it as a static class, but if you want to follow design patterns, consider AbstractFactory) you should use objects. So, having some copy of the same object that has only methods isn't necessary and is also memory-wasting.

Those are two main reason to use singleton to me.

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
DonCallisto
  • 29,419
  • 9
  • 72
  • 100
  • @DonCallisto If i understand correctly, it is simply a way to structure the code and it is nothing to do with restricting user until the transaction finishes. Am i correct? – karthik_spain Jul 20 '14 at 16:03
  • 1
    @karthik_spain: well, we can't say that because we need to study the particular case. But we can say that yes, is "just" a way to structure the code forcing an object to be "unique" into the whole system for aforementioned reasons. To prevent concurrency there are much goods methods and I'm afraid that singleton isn't one of those :) – DonCallisto Jul 20 '14 at 16:07
5

Yes, You are right "it cannot be instantiated more than once." and this concept is very useful when you opening a database connection.

Suppose,

If someone logins, you make new database object.

If someone updates something, you make a new database object.

If someone logouts, you make a new database object.

As you can see, every time if there is interaction with database, a new object will be created and a new connection will be opened. That's a bad thing in term of efficiency.

Here singleton class really solves the problem. It makes a database connection object and holds it, whenever required it just returns it instead of ocreate a new one.

class DB{
private static $_instance = null;
private $_pdo;

        private function __construct(){
            try{
                $this->_pdo = new PDO('mysql:host ='yourhost'; dbname = 'your_database','username','password);
                echo 'connected';

            }catch(PDOException $e){
                die($e->getMessage());
            }
        }
      public static function getInstance(){
          if(!isset(self::$_instance)){
              self::$_instance = new DB();
    }
    return self::$_instance; 
     }
  }

As you can see this class checks for existing connection ($_instance attribute), and returns it if it's not been set.

0

More Reference: Is there a use-case for singletons with database access in PHP?

From Design Patterns - PHP: The Right Way:

When designing web applications, it often makes sense conceptually and architecturally to allow access to one and only one instance of a particular class. The singleton pattern enables us to do this.

<?php
class Singleton
{
    /**
     * Returns the *Singleton* instance of this class.
     *
     * @staticvar Singleton $instance The *Singleton* instances of this class.
     *
     * @return Singleton The *Singleton* instance.
     */
    public static function getInstance()
    {
        static $instance = null;
        if (null === $instance) {
            $instance = new static();
        }

        return $instance;
    }

    /**
     * Protected constructor to prevent creating a new instance of the
     * *Singleton* via the `new` operator from outside of this class.
     */
    protected function __construct()
    {
    }

    /**
     * Private clone method to prevent cloning of the instance of the
     * *Singleton* instance.
     *
     * @return void
     */
    private function __clone()
    {
    }

    /**
     * Private unserialize method to prevent unserializing of the *Singleton*
     * instance.
     *
     * @return void
     */
    private function __wakeup()
    {
    }
}

class SingletonChild extends Singleton
{
}

$obj = Singleton::getInstance();
var_dump($obj === Singleton::getInstance());             // bool(true)

$anotherObj = SingletonChild::getInstance();
var_dump($anotherObj === Singleton::getInstance());      // bool(false)

var_dump($anotherObj === SingletonChild::getInstance()); // bool(true)

The code above implements the singleton pattern using a static variable and the static creation method getInstance(). Note the following:

  • The constructor __construct is declared as protected to prevent creating a new instance outside of the class via the new operator.
  • The magic method __clone is declared as private to prevent cloning of an instance of the class via the clone operator.
  • The magic method __wakeup is declared as private to prevent unserializing of an instance of the class via the global function unserialize().
  • A new instance is created via late static binding in the static creation method getInstance() with the keyword static. This allows the subclassing of the class Singleton in the example.

The singleton pattern is useful when we need to make sure we only have a single instance of a class for the entire request lifecycle in a web application. This typically occurs when we have global objects (such as a Configuration class) or a shared resource (such as an event queue).

You should be wary when using the singleton pattern, as by its very nature it introduces global state into your application, reducing testability. In most cases, dependency injection can (and should) be used in place of a singleton class. Using dependency injection means that we do not introduce unnecessary coupling into the design of our application, as the object using the shared or global resource requires no knowledge of a concretely defined class.

Singleton pattern on Wikipedia

Community
  • 1
  • 1
Kailash Yadav
  • 1,880
  • 2
  • 18
  • 37