Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I access my MySQL database via PDO. I'm setting up access to the database, and my first attempt was to use the following:

The first thing I thought of is global:

$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'root', 'pwd');

function some_function() {
    global $db;
    $db->query('...');
}

This is considered a bad practice. After a little search, I ended up with the Singleton pattern, which

"applies to situations in which there needs to be a single instance of a class."

According to the example in the manual, we should do this:

class Database {
    private static $instance, $db;

    private function __construct(){}

    static function singleton() {
        if(!isset(self::$instance))
            self::$instance = new __CLASS__;

        return self:$instance;
    }

    function get() {
        if(!isset(self::$db))
            self::$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'user', 'pwd')

        return self::$db;
    }
}

function some_function() {
    $db = Database::singleton();
    $db->get()->query('...');
}

some_function();

Why do I need that relatively large class when I can do this?

class Database {
    private static $db;

    private function __construct(){}

    static function get() {
        if(!isset(self::$db))
            self::$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'user', 'pwd');

        return self::$db;
    }
}

function some_function() {
    Database::get()->query('...');
}

some_function();

This last one works perfectly and I don't need to worry about $db anymore.

How can I create a smaller singleton class, or is there a use-case for singletons that I'm missing in PHP?

like image 636
seriousdev Avatar asked Oct 06 '22 19:10

seriousdev


People also ask

When would you want to use a singleton?

It is used where only a single instance of a class is required to control the action throughout the execution. A singleton class shouldn't have multiple instances in any case and at any cost. Singleton classes are used for logging, driver objects, caching and thread pool, database connections.

How can we avoid singletons?

Serialization is used to convert an object of byte stream and save in a file or send over a network. Suppose you serialize an object of a singleton class. Then if you de-serialize that object it will create a new instance and hence break the singleton pattern.

How would you create a singleton class using PHP?

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.


1 Answers

Singletons have very little - if not to say no - use in PHP.

In languages where objects live in shared memory, Singletons can be used to keep memory usage low. Instead of creating two objects, you reference an existing instance from the globally shared application memory. In PHP there is no such application memory. A Singleton created in one Request lives for exactly that request. A Singleton created in another Request done at the same time is still a completely different instance. Thus, one of the two main purposes of a Singleton is not applicable here.

In addition, many of the objects that can conceptually exist only once in your application do not necessarily require a language mechanism to enforce this. If you need only one instance, then don't instantiate another. It's only when you may have no other instance, e.g. when kittens die when you create a second instance, that you might have a valid Use Case for a Singleton.

The other purpose would be to have a global access point to an instance within the same Request. While this might sound desirable, it really isnt, because it creates coupling to the global scope (like any globals and statics). This makes Unit-Testing harder and your application in general less maintainable. There is ways to mitigate this, but in general, if you need to have the same instance in many classes, use Dependency Injection.

See my slides for Singletons in PHP - Why they are bad and how you can eliminate them from your applications for additional information.

Even Erich Gamma, one of the Singleton pattern's inventors, doubts this pattern nowadays:

"I'm in favor of dropping Singleton. Its use is almost always a design smell"

Further reading

  • How is testing the registry pattern or singleton hard in PHP?
  • What are the disadvantages of using a PHP database class as a singleton?
  • Database abstraction class design using PHP PDO
  • Would singleton be a good design pattern for a microblogging site?
  • Modifying a class to encapsulate instead of inherit
  • How to access an object from another class?
  • Why Singletons have no use in PHP
  • The Clean Code Talks - Singletons and Global State

If, after the above, you still need help deciding:

Singleton Decision Diagram

like image 124
Gordon Avatar answered Oct 11 '22 18:10

Gordon