0

我正在尝试重新编码我制作的主页。这次我想使用 OOP 风格,但我总是得到以下错误:

Statistic::checkExistingCounter() [statistic.checkexistingcounter]: 无法获取 MySQL

我究竟做错了什么?我知道准备语句是毫无意义的,但即使只是一个查询而不是准备语句也根本不起作用。

同样的错误:

无法获取 MySQL

我的数据库类:

class MySQL extends MySQLi {

    private static $_instance = null;
    private $host, $username, $password, $db;

    public static function getInstance() {
        if (!(self::$_instance instanceof self)) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    public function __construct(){
        $this->host = '...';
        $this->username = '...';
        $this->password = '...';
        $this->database = '...';
        $this->connect();
    }

    public function __destruct() {
        $this->db->close();
    }

    private function __clone(){} 

    public function connect() {
        $this->db = @new MySQLi($this->host, $this->username, $this->password, $this->database);

        /* change character set to utf8 */
        $this->db->set_charset("utf8");

        if (mysqli_connect_errno()) {
            printf("Connect failed: %s\n", mysqli_connect_error());
            exit();
        }

        return $this->db;
    }
}

我的统计类:

 class Statistic {
    private $remote, $user_agent, $referer; 
    private $db;

    /**
     * Create Instance of MySQL
     **/
    function __construct($db) {
        $this->db = MySQL::getInstance();
    }

    /**
     * Check for counter today
     *
     * @param: string SQL
     * @return: boolean (true = Counter exists, false = Counter doesnt exist)
     **/
    function checkExistingCounter($sql) {
        $stmt = $this->db->prepare($sql);

        $this->db->error;

        if (!$stmt) {
            echo 'Datenbankfehler';
            exit;
        }

        $stmt->execute();
        $stmt->store_result();

        if ($stmt->num_rows) {
            $stmt->close();
            return true;
        } else {
            $stmt->close();
            return false;
        }
    }

    function counter() {
        $sql = "SELECT ID FROM Counter WHERE Datum = CURDATE()";
        $checkCounter = $this->checkExistingCounter($sql);
    }

这是我的 index.php 的一部分:

$db = new MySQL();
$statistic = new Statistic($db);
$statistic->counter();
4

1 回答 1

1

您似乎在这里陷入困境,实现了两组相互竞争的编码模式:

  • 您的MySQL类既扩展MySQLi(即任何MySQL对象也是MySQLi对象)并“委托”到MySQLi其私有变量中的实例$db
  • 您的StatisticMySQL在其构造函数中获取一个实例(“依赖注入”),但随后忽略它并要求MySQL该类提供“单例”实例。

您需要更仔细地阅读每种模式的用途,并在每种情况下(继承委托、依赖注入单例)决定其中一种。

目前,您的代码将执行以下操作:

  1. 创建一个新MySQL对象(这也是一个MySQLi对象,但尚未初始化为任何特定的数据库连接,因为您还没有调用parent::__construct()
  2. MySQL构造函数中,设置$this->host
  3. connect()方法中,创建一个新MySQLi对象,将其传递给主机等
  4. 将此对象另存为$this->db,它只在析构函数 ( $this->db->close())中被引用
  5. 从 中返回MySQLi对象connect(),但没有__construct()查看该返回值
  6. 回到外部代码中,MySQL对象被传递给Statistic类的构造函数
  7. 然后构造函数忽略它,并调用 SingletonMySQL::getInstance()方法
  8. getInstance()方法(因为这是第一次被调用)将创建第二个MySQL对象,重复步骤 1 到 5
  9. 这第二个MySQL对象将保存$this->dbStatistics对象上
  10. checkExistingCounter方法尝试$this->db用作MySQLi连接,但该MySQL对象从未连接到任何数据库,因此您会收到错误消息。(有一个已连接的连接,如果它不是私有的,您可以将其作为$this->db->db.在第 7 步。)
于 2013-03-11T02:08:26.997 回答