php - 如何为 PDO 制作单例包装器?

标签 php pdo

如何制作 PDO 扩展的单例?扩展不起作用,因为我在尝试时遇到 fatal error ...

最佳答案

You don't need a Singleton.

但还是要回答这个问题:

您无法将公开可见性转变为更严格的可见性。因此 PDO 不能将构造函数的可见性更改为 public 以外的任何内容。所以你需要将 PDO 实例包装成一个 Singleton:

class MyPdo
{
    /**
     * @var MyPdo
     */
    protected static $_instance;

    /**
     * @var Pdo
     */
    protected $_pdo;

    /**
     * Creates instance and returns it on subsequent calls
     * 
     * @throws  InvalidArgumentException
     * @param   array $options PDO connection data
     * @returns MyPdo
     */
    public static function getInstance(array $options = NULL)
    {
        if(self::$_instance === NULL) {

            if($options === NULL) {
                throw new InvalidArgumentException(
                    'You must supply connection options on first run');
            }

            // call constructor with given options and assign instance
            self::$_instance = new self(
                $options['dsn'], 
                $options['user'], 
                $options['password'],
                $options['driver_options']
            );
        }

        return self::$_instance;
    }

    /**
     * Creates new MyPdo wrapping a PDO instance
     * 
     * @throws PDOException
     * @param  String $dsn
     * @param  String $user
     * @param  String $password
     * @param  Array  $driver_options
     * @return void
     */
    private function __construct($dsn, $user, $password, $driver_options)
    {
        try {
            $this->_pdo = new PDO($dsn, $user, $password, $driver_options);
        } catch (PDOException $e) {
            echo 'Connection failed: ' . $e->getMessage();
        }
    }

    /**
     * Singletons may not be cloned
     */
    private function __clone() {}

    /**
     * Delegate every get to PDO instance
     *  
     * @param  String $name
     * @return Mixed
     */
    public function __get($name)
    { 
        return $this->_pdo->$name;
    }

    /**
     * Delegate every set to PDO instance
     *  
     * @param  String $name
     * @param  Mixed  $val
     * @return Mixed
     */    
    public function __set($name, $val)
    { 
        return $this->_pdo->$name = $val; 
    }

    /**
     * Delegate every method call to PDO instance
     *  
     * @param  String $method
     * @param  Array  $args
     * @return Mixed
     */    
    public function __call($method, $args) {
        return call_user_func_array(array($this->_pdo, $method), $args);
    }
}

你会像这样使用它:

$db = MyPdo::getInstance(array(
    'dsn'=>'mysql:dbname=mysql;host=127.0.0.1',
    'user' => 'root',
    'password' => 'minnymickydaisydonaldplutogoofysanfrancisco',
    'driver_options' => array(
        PDO::MYSQL_ATTR_INIT_COMMAND =>  "SET NAMES utf8"
    )));

$version = $db->query( 'SELECT version();' );
echo $version->fetchColumn();

// remove reference to instance
unset($db);

// doesn't require connection data now as it returns same instance again
$db = MyPdo::getInstance();
$version = $db->query( 'SELECT version();' );
echo $version->fetch();

关于php - 如何为 PDO 制作单例包装器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2684179/

相关文章:

php - 单选按钮表单代码和下拉菜单代码

php - 了解 sql 错误和自动增量值中的 pdo rollback()

php - PDO 查询一半时间返回 False

php - 获取空查询

javascript - Onclick anchor 链接使用ajax只传递一个变量而不传递两个变量

php - 从 MySQL 中以正确的精度选择 float

javascript - 支付后点击浏览器返回按钮返回不同页面

php - 为什么我不应该在 PHP 中使用 mysql_* 函数?

php - 如果 PDO 事务失败,如何重定向到一个页面?

php - 尝试为 Rocket U2 构建 PHP PDO 扩展