简体   繁体   中英

Single instance of a MySQL database connection via PHP Class

I have the following database class. My thinking was that this will check for an existing instance of the class and return that rather than create a new database connection.

When I run the code it creates a connection. When I refresh the page another connection is created (checked MySQL connections).

Is my thinking incorrect? Fairly new to using OOP so apologies for the newbie question!

Any help or pointers in the right direction would be appreciated.

Many thanks.

<?php
class Db
{
    private $_connection;
    private static $_instance; 
    private $_host = 'localhost';
    private $_username = 'root';
    private $_password = 'password';
    private $_database = 'test';

    public static function getInstance()
    {
        if (!self::$_instance) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    private function __construct()
    {
        try {
            $this->_connection  = new PDO("mysql:host=$this->_host;dbname=$this->_database", $this->_username, $this->_password); 
            echo 'Connected to database';
        } catch (PDOException $e) {
            echo $e->getMessage();
        }
    }

    private function __clone()
    {
    }

    public function getConnection()
    {
    return $this->_connection;
    }
}

$db = Db::getInstance();

PHP is a " shared nothing " environment. Each request handled by a PHP application is isolated from all other requests either as a separate thread or a separate process depending on the server api (SAPI) being used. The class you have designed is a singleton but it is isolated to a single request-response cycle. This means that if you call Db::getInstance() 10 times during a single request you will get 10 references to the same object, but a single call in a separate request will create and return a distinct object.

You can use some type of connection pooling, either on the server or application side, to reduce the number of concurrent connections made to your backend database server. PHP's PDO abstraction enables application side connection pooling via the PDO::ATTR_PERSISTENT connection driver option. These pooled connections are cached in the PHP parent process rather than the worker thread/process that handles a request and subsequently reused. The exact number of connections that will be opened and how they are shared is variable depending on your SAPI and underlying database type.

When utilizing PHP for your server side language, understanding what happens in the background is probably a good thing.

PHP initiates the connection for you when you run that code. It does not persist the connection past the page load.

On each page load new connections will be opened so you can continue to make your requests and perform your tasks.

Consider what would happen if it did. You close the page and go to sleep and the server sits with an open connection to the database forever. You get a few visitors and then you hit your connection limit and get a too many connections error.

There are probably some references to cite, but I really can't find many as this is more of a logical problem then a coding problem.

Each time you refresh your page, you are instantiating a brand new Db object, and assigning it to a brand new variable called $db, so you get connections each time. I also think you may be overcomplicating your Db class.

When I reate db class to wrap PDO or mysqli, the idea is to create a db object, that when instantiated would include a database connection as one of it's attributes. To accomplish that, I'd rewrite your class a bit. Something like this would be all you need to create Db object with a private connection that can be used by any range of other methods you wish to add to the class... Say, a method to issue a query,

class Db
{
    private $_connection;
    private $_host = 'localhost';
    private $_username = 'root';
    private $_password = 'flindersbeast';
    private $_database = 'flinders';

    public function __construct()
    {
        try {
            $this->_connection = new PDO("mysql:host=$this->_host;dbname=$this->_database", $this->_username, $this->_password); 
            echo 'Connected to database';
        } catch (PDOException $e) {
            echo $e->getMessage();
        }
    }

    // Other methods here will use $this->_connection to do a variety of things.
    public function example()
    {
     // Do stuff - as needed you can pass $this->_connection to PDO 
    }
}

$db = new Db;

Good luck!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM