使用php singleton的几个mysqli查询

时间:2016-03-04 14:40:33

标签: php mysqli singleton

我有一个非常常见的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);

} }

所以似乎第二个连接不知何故被打扰了??

奖金问题:从我的知识来看,显然现在大多数人都嘲笑单身模式似乎很适合这个目的?

非常感谢任何帮助和选择!

3 个答案:

答案 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

http://php.net/manual/de/mysqli.connect-errno.php

http://php.net/mysqli_set_charset