我有一段代码,根据请求的URL,将包含十四个其他文件中的一个。这14个文件中的一些需要连接到三个不同数据库中的一个,并且可以随时添加其他文件。
我不希望默认情况下将PDO连接打开到所有三个数据库,因为它浪费资源并且会缩短执行时间。所以我的想法是将所有SQL查询包装在一个函数中。第一次在非开放PDO连接上执行查询时,try {}错误处理程序可以捕获它,找出问题所在(在这种情况下连接不存在),然后打开连接并重新执行查询。这样,数据库只在需要时连接 - 只要连接字符串(主机,数据库,用户名,密码)都是事先定义的,我就看不到它工作中的任何问题。
但是,我需要继续使用它,并且大约7天内无法访问开发框,所以任何人都可以看到该方案有任何问题吗?此外,任何人都可以给我一个错误信息,如果没有打开连接,处理程序 - > errorInfo()将返回?
答案 0 :(得分:12)
准确使用此类,如何使用PDO
类。
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.
}
答案 1 :(得分:5)
这是正确的想法,但不是最好的实现。
包装SQL操作很好。但是你为什么不这样做呢:
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;
}
}
这有很多好处:
在您的具体情况下,您应该选择3个单独的Wrapper
课程。将所有内容放入一个类是可行的(三个不同的$db
变量),但可能比它的价值更令人困惑。
答案 2 :(得分:5)
我使用__call魔术方法采用了另一种方法,因此您不需要为每个方法创建单独的包装器。
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);
}
}
}
您只需要用PDOLazyConnector替换PDO实例,所以:
$dbh = new PDO($dsn, $user, $password, $driver_options);
使用:
$dbh = new PDOLazyConnector($dsn, $user, $password, $driver_options);
答案 3 :(得分:1)
PDO有一个持久连接选项 PDO :: ATTR_PERSISTENT 。
中的评论答案 4 :(得分:0)
function &get_pdo()
{
static $_PDO = null;
if ($_PDO === null)
{
$_PDO = new PDO('your DSN', 'username', 'password');
}
return $_PDO;
}
然后你就做了
$stmt = get_pdo()->prepare('...');
您可以通过扩展PDO类并向其添加静态单例函数来执行相同的操作。我发现这种方法比较简单。还让您有机会从堆栈中的任何位置调用它,而无需将您的连接放在参数中(根据具体情况,这可能是好的还是坏的。)