12

I've been working on a small project using PHP and MySQL. I've read a lot around about best practices on managing a connection and so on.

I've also implemented (following some posts found around) a singleton class to manage MySQL connections.

require_once 'config.inc.php';
class DbConn {

    private static $instance;
    private $dbConn;

    private function __construct() {}

    /**
     *
     * @return DbConn
     */
    private static function getInstance(){
        if (self::$instance == null){
            $className = __CLASS__;
            self::$instance = new $className;
        }

        return self::$instance;
    }

    /**
     *
     * @return DbConn
     */
    private static function initConnection(){
        $db = self::getInstance();
        $connConf = getConfigData();
        $db->dbConn = new mysqli($connConf['db_host'], $connConf['db_user'], $connConf['db_pwd'],$connConf['db_name']);
        $db->dbConn->set_charset('utf8');
        return $db;
    }

    /**
     * @return mysqli
     */
    public static function getDbConn() {
        try {
            $db = self::initConnection();
            return $db->dbConn;
        } catch (Exception $ex) {
            echo "I was unable to open a connection to the database. " . $ex->getMessage();
            return null;
        }
    }
}

But... If my website has like 10K visitors contemporaneously and I'm calling every time my singleton object, should I expect to have performance issues? I meant, shouldn't I have a kind of pool of connections instead of a singleton?

3
  • 5
    And what is the contradiction? You can just set up the connections to be persistent and use a singleton. This model is used so that a single request won't connect twice to the database, but two different clients will run two different instances of your script so will use two different connections Commented Feb 17, 2014 at 15:26
  • 1
    @mishu Sure. How stupid I am. Thanks! Commented Feb 17, 2014 at 15:30
  • 1
    @mishu: Thank you for explaining it. Many of us did not think about it. Commented Dec 14, 2016 at 23:43

1 Answer 1

15

Using singletons in PHP is considered bad practice. From my experience the most problematic issue with them are unit tests. It is hard to ensure that two tests are independent when testing singletons.

I would delegate the responsibility for the constraint "only one instance should exists" to the code which creates the Db object.

Also for me it looks like there is a misunderstanding in how Singletons work in PHP in contrast to other languages: If you have 10.000 concurrent requests for example, then each request runs in a separate PHP process or thread, meaning they will all have their own instance of the "singleton", there is no sharing of this object for more than a single request (when running PHP in common web backend scenarios)

There is no "connection pooling" in PHP, but you can use mysqli persistent connections for mysql. It can be achieved by passing the p: in front of the hostname when creating mysqli. This might help here, but handle it with care (meaning read the documentation first)


However, just for theory, a singleton in PHP must be aware of the fact that someone could use clone. Meaning in your case it would be possible to do that:

$db = DB::getInstance();
$db2 = clone $db; 

To avoid that you can implement the __clone() method like this:

public function __clone() {
    throw new Exception("Can't clone a singleton");
}
Sign up to request clarification or add additional context in comments.

10 Comments

thanks a lot. What would you suggest me otherwise? I read about Dependency Injection. Cheers!
This is not related. I would just do $db = new Db() and then make sure that this instance is accessible from all levels of code which need them. Symfony2 is using their Service concept. IMO this makes sense and is a good design approach.. (Never thought that it will come the day when I'm saying this about symfony :) But I did, and think this is a nice implementation) ... Check this: symfony.com/doc/current/book/service_container.html
Generally avoiding Singletons for the sake of avoiding singletons is considered bad practice as well. There is a correct time and place for every sort of pattern, just don't over or underuse them.
@GillesLesire Indeed, DB singletons are one of the most applicable use cases for singletons in PHP. Followed by singletons used in WordPress plugins.
@unity100 How do you make sure that multiple unit tests don't influence each other when implementing the DB class as a singleton?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.