我有一个非常常见的mysqli类,为应用程序的其余部分提供数据库连接:
class IabDB extends mysqli {
private static $instance = null;
// db connection config vars
private $user = "xxx-lit";
private $pass = "xxx";
private $dbName = "xxx";
private $dbHost = "xxx";
private function __construct() {
parent::__construct($this->dbHost, $this->user, $this->pass, $this->dbName);
if (mysqli_connect_error()) {
exit('Connect Error (' . mysqli_connect_errno() . ') '
. mysqli_connect_error());
}
mysqli_set_charset($this, "utf8");
}
public static function getInstance() {
if (!self::$instance instanceof self) {
self::$instance = new self;
}
return self::$instance;
}
在我的模型中,我会检索这样的数据,效果很好:
$db = IabDB::getInstance();
$query = $db->query("SELECT status, username, email, id FROM " . $table);
$items = $query->fetch_all();
修改 但是当我尝试为另一个查询获取另一个实例时,我收到错误消息:在null上调用成员函数fetch_all()。
相信我:我来回试了一下。两个查询都有效,如果只使用其中一个查询,则返回结果。仅仅为了完整起见,这是第二个模型:
class Model {
public static function getItems($table) {
$db = IabDB::getInstance();
$query = $db->query("SELECT * FROM lit_veranstaltungen");
$items = $query->fetch_all();
$db->close();
var_dump($items);
} }
所以似乎第二个连接不知何故被打扰了??
奖金问题:从我的知识来看,显然现在大多数人都嘲笑单身模式似乎很适合这个目的?
非常感谢任何帮助和选择!
答案 0 :(得分:2)
您的代码适用于我,无论我获得多少实例:
$db = IabDB::getInstance();
$query = $db->query("SELECT name FROM users limit 1");
$items = $query->fetch_all();
var_export($items);
$db = IabDB::getInstance();
$query = $db->query("SELECT name FROM users limit 1,1");
$items = $query->fetch_all();
var_export($items);
返回
array ( 0 => array ( 0 => 'John', ), )
array ( 0 => array ( 0 => 'Mike', ), )
因此,我认为您运行的特定查询存在错误。因此,您需要为查询提供更好的错误报告。将构造函数更改为此
private function __construct() {
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
parent::__construct($this->dbHost, $this->user, $this->pass, $this->dbName);
$this->set_charset("utf8");
}
然后确保您的PHP配置如下
error_reporting(E_ALL);
ini_set('display_errors',1);
然后再次运行您的代码。
它将报告错误或返回空数组。在后一种情况下,它意味着数据库中没有与您的第二个查询条件匹配的行。例如,对于像这样的代码
$db = IabDB::getInstance();
$query = $db->query("SELECT name FROM users WHERE 1=0");
$items = $query->fetch_all();
var_export($items);
$db = IabDB::getInstance();
$query = $db->query("SELECT name FOrM users");
$items = $query->fetch_all();
var_export($items);
它将为第一个片段返回一个空数组,为第二个片段返回错误:
array()
致命错误:未捕获的异常'mysqli_sql_exception',消息'您的SQL语法中有错误;检查与您的MySQL服务器版本相对应的手册,以便在第1行<'p>的“用户”附近使用正确的语法
另外,我建议您添加这样的功能
public function query_params($query, $params, $types = NULL)
{
$statement = $this->prepare($query);
$types = $types ?: str_repeat('s', count($params));
$statement->bind_param($types, ...$params);
$statement->execute();
return $statement->get_result();
}
可让您像使用PDO一样轻松地使用预准备语句:
$user = $db->query_params("SELECT * FROM users WHERE name = ?", ['Mike'])->fetch_assoc();
关于singleton,如果你使用的是旧式程序PHP,那么singleton就可以了。如果您正在使用OOP,那么最好实现基于依赖注入的方法。
答案 1 :(得分:1)
由于mysqli(和PDO)类构造函数是公共的,因此无法从扩展mysqli(或PDO)的类生成单例。您不能覆盖公共父的构造函数,并在继承的子类中将其设为私有!试试吧,你会收到以下错误:
Fatal error: Access level to DataBase::__construct() must be public (as in class mysqli)
答案 2 :(得分:0)
执行查询后尝试使用$query->close();
。
对于这种情况,单身人士并不是个坏主意。但更常见的是,你有类似“连接管理器”的东西,它在第一次使用时创建一个mysqli对象,然后在连续调用时返回该对象,能够与多个数据库或不同用户建立多个连接。
这样的事情:
class DBConnection {
protected static $connections = array();
public static function getConnection($connection_name = 'default') {
if (!isset(static::$connections[$connection_name])) {
static::$connections[$connection_name] = // setup connection
// ... error handling and stuff
}
return static::$connections[$connection_name];
}
}
Btw。:在你的构造函数中,我会使用mysqli对象的属性进行错误处理:
http://php.net/manual/de/mysqli.connect-error.php