PHP单例设计PDO
PHP Singleton design PDO
多年来,我一直在我的网站上使用 PDO 的单例设计 PHP5。
我现在正在迁移到 PHP7,我在我的 Apache 日志文件中看到错误:
PHP Notice: Accessing static property Db::$PDOInstances as non static in /var/www/class/class_db_test.php on line 12
PHP Notice: Accessing static property Db::$PDOInstances as non static in /var/www/class/class_db_test.php on line 13
PHP Notice: Accessing static property Db::$PDOInstances as non static in /var/www/class/class_db_test.php on line 32
这是我的单例 class 用于数据库访问:
<?php
require_once(dirname(__FILE__) . "/../setting.php");
class Db {
private static $debug = 1;
private static $debugPath = "/tmp/sql_debug.log";
private static $PDOInstances = array("db1"=>"","db2"=>"");
private function __construct($db_type){
switch($db_type) {
case "db1":
$this->PDOInstances[$db_type] = new PDO('mysql:dbname='.DB_NAME.';host='.DB_HOST,DB_USER ,DB_PWD,array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
$this->PDOInstances[$db_type]->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
break;
case "db2":
$this->PDOInstances[$db_type] = new PDO('mysql:dbname='.DB2_NAME.';host='.DB2_HOST,DB2_USER ,DB2_PWD,array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
$this->PDOInstances[$db_type]->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
break;
}
}
public static function getInstance($db_type) {
if(self::$debug == 1){self::sqlDebug("connection","");}
if(self::$PDOInstances[$db_type] == null){
self::$PDOInstances[$db_type] = new self($db_type);
}
return self::$PDOInstances[$db_type];
}
public function query($db_type,$query){
if(self::$debug == 1){self::sqlDebug("read request",$query);}
return $this->PDOInstances[$db_type]->query($query);
}
public function exec($db_type,$query){
if(self::$debug == 1){self::sqlDebug("request",$query);}
return $this->PDOInstances[$db_type]->exec($query);
}
public function lastInsertId($db_type){
return $this->PDOInstances[$db_type]->lastInsertId();
}
public function quote($db_type,$string){
if(self::$debug == 1){self::sqlDebug("quote",$string);}
return $this->PDOInstances[$db_type]->quote($string);
}
public static function sqlDebug($_mode,$_query){
$today = date("m.d.y-H:m:s");
if($_mode == "connection"){
$line = $today." Connection: '".$_query."'\r\n";
}
else if($_mode == "quote"){
$line = $today." Quote : '".$_query."'\r\n";
}
else if($_mode == "request"){
$line = $today." Request : '".$_query."'\r\n";
}
else if($_mode == "read request"){
$line = $today." Read request : '".$_query."'\r\n";
}
$file_debug = fopen(self::$debugPath, "a+");
fwrite($file_debug, $line);
fflush($file_debug);
fclose($file_debug);
}
}
?>
还有我的测试代码:
<?php
error_reporting(E_ALL);
require_once(dirname(__FILE__) . "/setting.php");
require_once(dirname(__FILE__) . "/class/class_db_test.php");
$con = Db::getInstance("db1");
$res = $con->query("db1","SELECT userId from user WHERE userName='test'");
if($res->rowCount() == 1){
$line = $res->fetchAll();
$res->closeCursor();
echo $line[0]['userId'];
}
else{
echo "0";
}
?>
当我在第 12、13 和 32 行将 $this 更改为 self:: 时,出现以下错误:
PHP Warning: Missing argument 2 for Db::query(), called in /var/www/class/class_db_test.php on line 32 and defined in /var/www/class/class_db_test.php on line 30
PHP Notice: Undefined variable: query in /var/www/class/class_db_test.php on line 31
PHP Notice: Undefined index: SELECT userId from user WHERE userName='test' in /var/www/class/class_db_test.php on line 32
PHP Fatal error: Uncaught Error: Call to a member function query() on null in /var/www/class/class_db_test.php:32\nStack trace:\n#0 /var/www/class/class_db_test.php(32): Db->query('SELECT userId f...')\n#1 /var/www/test.php(8): Db->query('db1', 'SELECT userId f...')\n#2 {main}\n thrown in /var/www/class/class_db_test.php on line 32
关于如何调整我的代码以使其在 PHP7 上运行,您有什么想法吗?
谢谢
我能看到的主要内容之一是您以两种不同的方式使用 PDOInstances
。它用于 Db
class 的实例列表(在 getInstance()
静态方法中设置)。但它似乎也是您尝试为数据库存储 PDO
实例的地方(在构造函数中)。
如果您更改用于存储数据库的变量(Db
class),那么这至少意味着您拥有两条数据...
private $PDOInstances = array("db1"=>"","db2"=>""); // Remove static
private static $DbInstances = array("db1"=>"","db2"=>"");
public static function getInstance($db_type) {
if(self::$debug == 1){self::sqlDebug("connection","");}
if(self::$DbInstances[$db_type] == null){
self::$DbInstances[$db_type] = new self($db_type);
}
return self::$DbInstances[$db_type];
}
我也不确定你为什么打电话
$con = Db::getInstance("db1");
然后您需要将数据库类型传递给所有其他方法...
$res = $con->query("db1","SELECT userId from user WHERE userName='test'");
当然这应该由使用数据库类型调用的连接暗示。
如果在构造函数中你刚刚做了(设置 PDOInstances
没有数组部分)
$this->PDOInstances = new PDO('mysql:dbname='.DB_NAME.';host='.DB_HOST,DB_USER ,DB_PWD,array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
那么数据库的所有访问都是通过这个完成的...
public function query($query){
if(self::$debug == 1){self::sqlDebug("read request",$query);}
return $this->PDOInstances->query($query);
}
考虑到 Nigel Ren 的回答,这里是修改后的 Db class 文件:
<?php
require_once(dirname(__FILE__) . "/../setting.php");
class Db {
private static $debug = 1;
private static $debugPath = "/tmp/sql_debug.log";
private $PDOInstances = ""; // Remove static
private static $DbInstances = array("db1"=>"","db2"=>"");
private function __construct($db_type){
switch($db_type) {
case "db1":
$this->PDOInstances = new PDO('mysql:dbname='.DB_NAME.';host='.DB_HOST,DB_USER ,DB_PWD,array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
$this->PDOInstances->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
break;
case "db2":
$this->PDOInstances = new PDO('mysql:dbname='.DB2_NAME.';host='.DB2_HOST,DB2_USER ,DB2_PWD,array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
$this->PDOInstances->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
break;
}
}
public static function getInstance($db_type) {
if(self::$debug == 1){self::sqlDebug("connection","");}
if(self::$DbInstances[$db_type] == null){
self::$DbInstances[$db_type] = new self($db_type);
}
return self::$DbInstances[$db_type];
}
public function query($query){
if(self::$debug == 1){self::sqlDebug("read request",$query);}
return $this->PDOInstances->query($query);
}
public function exec($query){
if(self::$debug == 1){self::sqlDebug("request",$query);}
return $this->PDOInstances->exec($query);
}
public function lastInsertId(){
return $this->PDOInstances->lastInsertId();
}
public function quote($string){
if(self::$debug == 1){self::sqlDebug("quote",$string);}
return $this->PDOInstances->quote($string);
}
public static function sqlDebug($_mode,$_query){
$today = date("m.d.y-H:m:s");
if($_mode == "connection"){
$line = $today." Connection: '".$_query."'\r\n";
}
else if($_mode == "quote"){
$line = $today." Quote : '".$_query."'\r\n";
}
else if($_mode == "request"){
$line = $today." Request : '".$_query."'\r\n";
}
else if($_mode == "read request"){
$line = $today." Read request : '".$_query."'\r\n";
}
$file_debug = fopen(self::$debugPath, "a+");
fwrite($file_debug, $line);
fflush($file_debug);
fclose($file_debug);
}
}
?>
和测试文件:
<?php
error_reporting(E_ALL);
require_once(dirname(__FILE__) . "/setting.php");
require_once(dirname(__FILE__) . "/class/class_db_test.php");
$con = Db::getInstance("db1");
$res = $con->query("SELECT userId from user WHERE userName='test'");
if($res->rowCount() == 1){
$line = $res->fetchAll();
$res->closeCursor();
echo $line[0]['userId'];
}
else{
echo "0";
}
?>
一切正常,没有 PHP Notice/Error。
谢谢!
多年来,我一直在我的网站上使用 PDO 的单例设计 PHP5。 我现在正在迁移到 PHP7,我在我的 Apache 日志文件中看到错误:
PHP Notice: Accessing static property Db::$PDOInstances as non static in /var/www/class/class_db_test.php on line 12
PHP Notice: Accessing static property Db::$PDOInstances as non static in /var/www/class/class_db_test.php on line 13
PHP Notice: Accessing static property Db::$PDOInstances as non static in /var/www/class/class_db_test.php on line 32
这是我的单例 class 用于数据库访问:
<?php
require_once(dirname(__FILE__) . "/../setting.php");
class Db {
private static $debug = 1;
private static $debugPath = "/tmp/sql_debug.log";
private static $PDOInstances = array("db1"=>"","db2"=>"");
private function __construct($db_type){
switch($db_type) {
case "db1":
$this->PDOInstances[$db_type] = new PDO('mysql:dbname='.DB_NAME.';host='.DB_HOST,DB_USER ,DB_PWD,array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
$this->PDOInstances[$db_type]->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
break;
case "db2":
$this->PDOInstances[$db_type] = new PDO('mysql:dbname='.DB2_NAME.';host='.DB2_HOST,DB2_USER ,DB2_PWD,array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
$this->PDOInstances[$db_type]->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
break;
}
}
public static function getInstance($db_type) {
if(self::$debug == 1){self::sqlDebug("connection","");}
if(self::$PDOInstances[$db_type] == null){
self::$PDOInstances[$db_type] = new self($db_type);
}
return self::$PDOInstances[$db_type];
}
public function query($db_type,$query){
if(self::$debug == 1){self::sqlDebug("read request",$query);}
return $this->PDOInstances[$db_type]->query($query);
}
public function exec($db_type,$query){
if(self::$debug == 1){self::sqlDebug("request",$query);}
return $this->PDOInstances[$db_type]->exec($query);
}
public function lastInsertId($db_type){
return $this->PDOInstances[$db_type]->lastInsertId();
}
public function quote($db_type,$string){
if(self::$debug == 1){self::sqlDebug("quote",$string);}
return $this->PDOInstances[$db_type]->quote($string);
}
public static function sqlDebug($_mode,$_query){
$today = date("m.d.y-H:m:s");
if($_mode == "connection"){
$line = $today." Connection: '".$_query."'\r\n";
}
else if($_mode == "quote"){
$line = $today." Quote : '".$_query."'\r\n";
}
else if($_mode == "request"){
$line = $today." Request : '".$_query."'\r\n";
}
else if($_mode == "read request"){
$line = $today." Read request : '".$_query."'\r\n";
}
$file_debug = fopen(self::$debugPath, "a+");
fwrite($file_debug, $line);
fflush($file_debug);
fclose($file_debug);
}
}
?>
还有我的测试代码:
<?php
error_reporting(E_ALL);
require_once(dirname(__FILE__) . "/setting.php");
require_once(dirname(__FILE__) . "/class/class_db_test.php");
$con = Db::getInstance("db1");
$res = $con->query("db1","SELECT userId from user WHERE userName='test'");
if($res->rowCount() == 1){
$line = $res->fetchAll();
$res->closeCursor();
echo $line[0]['userId'];
}
else{
echo "0";
}
?>
当我在第 12、13 和 32 行将 $this 更改为 self:: 时,出现以下错误:
PHP Warning: Missing argument 2 for Db::query(), called in /var/www/class/class_db_test.php on line 32 and defined in /var/www/class/class_db_test.php on line 30
PHP Notice: Undefined variable: query in /var/www/class/class_db_test.php on line 31
PHP Notice: Undefined index: SELECT userId from user WHERE userName='test' in /var/www/class/class_db_test.php on line 32
PHP Fatal error: Uncaught Error: Call to a member function query() on null in /var/www/class/class_db_test.php:32\nStack trace:\n#0 /var/www/class/class_db_test.php(32): Db->query('SELECT userId f...')\n#1 /var/www/test.php(8): Db->query('db1', 'SELECT userId f...')\n#2 {main}\n thrown in /var/www/class/class_db_test.php on line 32
关于如何调整我的代码以使其在 PHP7 上运行,您有什么想法吗?
谢谢
我能看到的主要内容之一是您以两种不同的方式使用 PDOInstances
。它用于 Db
class 的实例列表(在 getInstance()
静态方法中设置)。但它似乎也是您尝试为数据库存储 PDO
实例的地方(在构造函数中)。
如果您更改用于存储数据库的变量(Db
class),那么这至少意味着您拥有两条数据...
private $PDOInstances = array("db1"=>"","db2"=>""); // Remove static
private static $DbInstances = array("db1"=>"","db2"=>"");
public static function getInstance($db_type) {
if(self::$debug == 1){self::sqlDebug("connection","");}
if(self::$DbInstances[$db_type] == null){
self::$DbInstances[$db_type] = new self($db_type);
}
return self::$DbInstances[$db_type];
}
我也不确定你为什么打电话
$con = Db::getInstance("db1");
然后您需要将数据库类型传递给所有其他方法...
$res = $con->query("db1","SELECT userId from user WHERE userName='test'");
当然这应该由使用数据库类型调用的连接暗示。
如果在构造函数中你刚刚做了(设置 PDOInstances
没有数组部分)
$this->PDOInstances = new PDO('mysql:dbname='.DB_NAME.';host='.DB_HOST,DB_USER ,DB_PWD,array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
那么数据库的所有访问都是通过这个完成的...
public function query($query){
if(self::$debug == 1){self::sqlDebug("read request",$query);}
return $this->PDOInstances->query($query);
}
考虑到 Nigel Ren 的回答,这里是修改后的 Db class 文件:
<?php
require_once(dirname(__FILE__) . "/../setting.php");
class Db {
private static $debug = 1;
private static $debugPath = "/tmp/sql_debug.log";
private $PDOInstances = ""; // Remove static
private static $DbInstances = array("db1"=>"","db2"=>"");
private function __construct($db_type){
switch($db_type) {
case "db1":
$this->PDOInstances = new PDO('mysql:dbname='.DB_NAME.';host='.DB_HOST,DB_USER ,DB_PWD,array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
$this->PDOInstances->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
break;
case "db2":
$this->PDOInstances = new PDO('mysql:dbname='.DB2_NAME.';host='.DB2_HOST,DB2_USER ,DB2_PWD,array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
$this->PDOInstances->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
break;
}
}
public static function getInstance($db_type) {
if(self::$debug == 1){self::sqlDebug("connection","");}
if(self::$DbInstances[$db_type] == null){
self::$DbInstances[$db_type] = new self($db_type);
}
return self::$DbInstances[$db_type];
}
public function query($query){
if(self::$debug == 1){self::sqlDebug("read request",$query);}
return $this->PDOInstances->query($query);
}
public function exec($query){
if(self::$debug == 1){self::sqlDebug("request",$query);}
return $this->PDOInstances->exec($query);
}
public function lastInsertId(){
return $this->PDOInstances->lastInsertId();
}
public function quote($string){
if(self::$debug == 1){self::sqlDebug("quote",$string);}
return $this->PDOInstances->quote($string);
}
public static function sqlDebug($_mode,$_query){
$today = date("m.d.y-H:m:s");
if($_mode == "connection"){
$line = $today." Connection: '".$_query."'\r\n";
}
else if($_mode == "quote"){
$line = $today." Quote : '".$_query."'\r\n";
}
else if($_mode == "request"){
$line = $today." Request : '".$_query."'\r\n";
}
else if($_mode == "read request"){
$line = $today." Read request : '".$_query."'\r\n";
}
$file_debug = fopen(self::$debugPath, "a+");
fwrite($file_debug, $line);
fflush($file_debug);
fclose($file_debug);
}
}
?>
和测试文件:
<?php
error_reporting(E_ALL);
require_once(dirname(__FILE__) . "/setting.php");
require_once(dirname(__FILE__) . "/class/class_db_test.php");
$con = Db::getInstance("db1");
$res = $con->query("SELECT userId from user WHERE userName='test'");
if($res->rowCount() == 1){
$line = $res->fetchAll();
$res->closeCursor();
echo $line[0]['userId'];
}
else{
echo "0";
}
?>
一切正常,没有 PHP Notice/Error。
谢谢!