Auto connecting to PDO only if needed

前端 未结 5 2051
不思量自难忘°
不思量自难忘° 2020-12-17 04:27

I have a section of code that depending on the URL requested, will include one of fourteen other files. Some of these fourteen files require a connection to one of three di

相关标签:
5条回答
  • 2020-12-17 04:38
    function &get_pdo()
    {
        static $_PDO = null;
    
        if ($_PDO === null)
        {
            $_PDO = new PDO('your DSN', 'username', 'password');
        }
    
        return $_PDO;
    }
    

    Then you just do

    $stmt = get_pdo()->prepare('...');
    

    You could do the same by extending the PDO class and adding a static singleton function to it. I find this approach simplier. Also gives you the opportunity to call it from anywhere on the stack without having to put your connection in the arguments (which can be good or bad, depending on the situation).

    0 讨论(0)
  • 2020-12-17 04:44

    I took another approach using __call magic method so you don't need to create individual wrappers for every method.

    class PDOLazyConnector
    {
        private $dsn;
        private $username;
        private $password;
        private $driver_options;
        private $dbh;
    
        public function __construct ($dsn, $username, $password, $driver_options = array ())
        {
            $this->dsn = $dsn;
            $this->username = $username;
            $this->password = $password;
            $this->driver_options = $driver_options;
        }
    
        public function __call ($function, $args)
        {
            // connect to db (first time only)
            $this->__init_dbh ();
    
            // invoke the original method
            return call_user_func_array (array($this->dbh, $function), $args);
        }
    
        public function __get ($property)
        {
            return $this->dbh->$property;
        }
    
        private function __init_dbh ()
        {
            // If db handler is not open yet, do it now
            if (empty ($this->dbh)) {
                $this->dbh = new PDO ($this->dsn, $this->username, $this->password, $this->driver_options);
            }
        }       
    }
    

    You just have to replace your PDO instancing with PDOLazyConnector, so:

    $dbh = new PDO($dsn, $user, $password, $driver_options);
    

    with:

    $dbh = new PDOLazyConnector($dsn, $user, $password, $driver_options);
    
    0 讨论(0)
  • 2020-12-17 04:44

    PDO has an option for persistent connections PDO::ATTR_PERSISTENT.

    See the comments in http://php.net/manual/en/book.pdo.php

    0 讨论(0)
  • 2020-12-17 04:50

    This is the right idea, but not the best implementation of it.

    Wrapping the SQL operations is good. But why don't you do it this way:

    class Wrapper {
        private static $db;
    
        public static function someQuery() {
            $db = self::getDatabase();
            // now go on to execute the query
        }
    
        private static function getDatabase() {
            if (self::$db === null) {
                self::$db = // connect here
            }
            return self::$db;
        }
    }
    

    This has a lot of advantages:

    • Allows you to logically group SQL operations into one (or several!) classes
    • Does not connect to database if not needed
    • Does not depend on (brittle) error checks to function correctly

    In your specific case, you should probably go with 3 separate Wrapper classes. Putting everything into one class is doable (three different $db variables) but probably more confusing than it's worth.

    0 讨论(0)
  • 2020-12-17 04:57

    Use this class exactly how you would use the PDO class.

    class DB extends PDO {
    
        protected $_config = array();
    
        protected $_connected = false;
    
        public function __construct($dsn, $user = null, $pass = null, $options = null) {
            //Save connection details for later
            $this->_config = array(
                'dsn' => $dsn,
                'user' => $user,
                'pass' => $pass,
                'options' => $options
            );
        }
    
        public function checkConnection() {
            if (!$this->_connected) {
                extract($this->_config);
                parent::__construct($dsn, $user, $pass, $options)
                $this->_connected = true;
            }
        }
    
        public function query($query) {
            $this->checkConnection();
            return parent::query($query);
        }
    
        public function exec($query) {
            $this->checkConnection();
            return parent::exec($query);
        }
    
        //etc.
    }
    
    0 讨论(0)
提交回复
热议问题