How to make a database connection using the Singleton design standard

Asked

Viewed 2,452 times

1

Well I do many web applications, where I all use database, and every time I do a new project, I create a file responsible for making queries with the database (CRUD).

Only that I want to change this, I want to make a file where I have all these queries with the database, and I wanted to use the standard Singleton projects.

And I wanted a little help on how to put this file together.

  • 1

    I recommend this as an additional reading: http://answall.com/questions/18860/por-que-n%C3%A3o-devo-usar-Singleton/18933#18933

  • Video about Singleton in PHP: https://www.youtube.com/watch?v=hHKOLn0Lx7A

2 answers

5


The Pattern Singleton consists of always returning the same instance of a given class to any point in the application.

This is done by limiting the access to the constructor method and returning the instance through a static method, i.e., a method you can call without instantiating the class.

Follows a rapid implementation:

class BancoDeDados
{
    // Instância da classe
    private static $instance = null;
    private $conn;

    // Construtor privado: só a própria classe pode invocá-lo
    private function __construct()
    {
        $host = "localhost";
        $user = "root";
        $pswd = "root";
        $db = "banco";

        try {
            $this->conn = mysqli_connect($host, $user, $pswd, $db);
            $this->conn->set_charset('utf8');
        } catch (Exception $e) {
            die("Erro na conexão com MySQL! " . $e->getMessage());
        }
    }

    // método estático
    static function getInstance()
    {
        // Já existe uma instância?
        if (self::$instance == NULL)
            self::$instance = new BancoDeDados();   // Não existe, cria a instância 
        return self::$instance;                     // Já existe, simplesmente retorna
    }

    // Previne o uso de clone
    private function __clone() {}
}

// Usando a classe
$db = BancoDeDados::getInstance();

// Você não poderá fazer isso por causa do construtor privado:
$db = new BancoDeDados();

From there, develop methods for access to your bank class.

  • This code helped me a lot, but as I mentioned, I want to do CRUD operations. Should I do these static functions as well? Ex: Static Function updatedb().....

  • 1

    No, these operations you normally create in public methods.

4

Singleton

Intent:

Ensure a single instance and provide a global access point throughout the application’s use cycle

First, Singleton is not for database use. If you need to use multiple databases, what happens? Singleton becomes a problem. If you need a pattern for database, look for DAO (for example). And if you don’t use it yet, try to work with PDO in the PHP, because it is much safer, flexible and meets well.

Second, Singleton in the PHP is unfeasible. The reason? To each request http made the PHP automatically destroys all instances. Whatever language or technology is used, any situation where the answer destroys the instance singleton makes no sense, because a new instance is generated at each request.

When using a pattern you need to understand well what problem it proposes to solve, if it fits in the resolution of your problem and if the environment in which you will apply it will allow that purpose to be fulfilled. Anything other than this you should avoid using, because instead of solving your problem it will end up creating many others.

  • Dalton, Singleton really isn’t the best Pattern for this. But do not forget that each case is a case and it is up to the programmer’s expertise to evaluate its use. As you said, the goal of Pattern is to eliminate the problem of multiple instances. if you have this problem in an application (creation of several instances of the same object, even in the same php request) its use is yes beneficial.

  • A use case that happened to me. I have a legacy code that I’m working on. Its complete migration will take a few months and the Prod environment was suffering from great memory consumption between requests. I needed to do something. Analyzing some code snippets I discovered that the bank class was instantiated up to 8 times per request! In that case Singleton was my solution. I applied it to the bank class, replaced all the instances in the class and solved the memory consumption problem in less than 15 minutes. I did something wrong with applying Singleton ?

  • 1

    It is beneficial when well applied. Singleton is most often not used correctly. In PHP it would be feasible to use a web socket where the instance would not be destroyed, so you would actually have a single instance throughout the application usage cycle. Singleton loses meaning if the instance is destroyed. It is important to note that writing a correct Singleton is totally different from implementing it correctly, so it is very important to know well the motivation of the Patterns and their use cases.

  • About your use case, I believe that the Registry Pattern would be ideal.

  • http://avedo.net/101/the-registry-pattern-and-php/ - I understand that resgistry is a collection of instances, which always returns the same instance of an object. You are suggesting that I create one more class in a legacy code to ensure that I will always receive the same instance of a single object?

  • Registry is like a box that saves instances and uses the specific instance you saved when requested. Remember that making it work is different from using it correctly, Singleton worked and we know that is not the best solution for this use case. What I suggest is to refactor the legacy code and use the Patterns correctly. If it is not possible, even if you think you will have a little more work with Registry, it is what I recommend, after all the more bed Smells are added, the worse the application will be, even if it seems an efficient solution at the moment.

  • I am already migrating the legacy code into another project. I will use data mapper for database abstraction. I must waste more time with legacy code if Singleton solves the problem?

  • The decision is yours, if you need to use another bank in the legacy code you will have another headache with the use of Singleton.

  • This is not the case. Legacy code will not be further improved.

  • Okay, another thing: Without private Function __clone() you will not guarantee that your Singleton has a single instance while running the stream, as it can be cloned.

  • I really forgot about the clone. I edited the answer, thank you!

  • 2

    Dalton, please check out the guide How we should format questions and answers?, because its use of code formatting is mistaken. Thanks!

Show 7 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.