【问题标题】:PHP closing mysqli connection to database errorPHP关闭mysqli到数据库的连接错误
【发布时间】:2016-08-30 22:40:12
【问题描述】:

在尝试解决我的问题时,我遇到此错误的情况与我在 SO 上看到的情况不同。我有一个类,数据库,它只创建自己的一个实例,试图将与 mysql 服务器的连接数限制为一个。这是我的班级[code 1]

class Database {

    private $_connection;

    // Store the single instance.
    private static $_instance;

    /**
     * Get self instance of database to private static variable $_instance.
     * @param string $host
     * @param string $username
     * @param string $password
     * @param string $database
     * @return Database
     */
      public static function getInstance($host,$username,$password,$database) {
          if (!self::$_instance) {
              self::$_instance = new self($host,$username,$password,$database);
          }
          return self::$_instance;
      }

      /**
       * Constructor.
       * @param string $host
       * @param string $username
       * @param string $password
       * @param string $database
       */
       public function __construct($host,$username,$password,$database) {
           $this->_connection = new mysqli($host, $username, $password, $database);

        // Error handling.
        if (mysqli_connect_error()) {
            trigger_error('Failed to connect to MySQL: ' . mysqli_connect_error(), E_USER_ERROR);
        }
    }

    /**
    * Empty clone magic method to prevent duplication.
    */
     private function __clone() {}

     /**
     * Get the mysqli connection;
     */ 
      public function getConnection(){
          return $this->_connection;
      }
  }

在这节课之后,我创建了一个用于从表中获取一些信息的连接。代码如下[code 2]

    // Establish a connection with MySQL Server database.
    $host = 'localhost';
    $username = 'barbu';
    $password = 'watcrn0y';
    $database = 'siteinfo';

    $db = Database::getInstance($host, $username, $password, $database);
    $mysqli = $db->getConnection();

    // Get the firstname of the author of the site from database.
    $sql_query = 'SELECT author.firstname, author.lastname ';
    $sql_query .= 'FROM author;';

    $result = $mysqli->query($sql_query);


    if($result && $row = $result->fetch_assoc()){
        $author_firstname = $row['firstname'];
        $author_lastname = $row['lastname'];
    }

现在,在另一个文件中,我这样做[code 3]

require '../includes/siteinfo.php'; // this file contains the connection 
    // with first database ['siteinfo']. 
    //I include this file for accessing some other variables from it, which aren't  
   //in the code posted above. 

// Establish the connection to server.
$host = 'localhost';
$username = 'barbu';
$password = 'watcrn0y';
$database = 'articles';

// Here I need to close my previous connection and begin another.
// It is important to remember that my class is designed for creating 
// just one connection at a time.
// So if I want to change the connection to another database, 
// I have to close the previous one and create the one which 
// suits my needs.
$mysqli->close();
unset($db);

$db = Database::getInstance($host, $username, $password, $database);
$mysqli = $db->getConnection();



// Send the post info to the server.
$title = (isset($_POST['title'])) ? $_POST['title'] : '';
$text = (isset($_POST['text'])) ? $_POST['text'] : '';
$sql = "INSERT INTO postInfo ";
$sql .= "VALUES ('" . $author_firstname . " " . $author_lastname ."', '" . 
date('d D M Y') . "', '" . $title . "', '" . $text . "');";
$result = $mysqli->query($sql);

执行此操作时,我收到错误:

警告:mysqli::query():无法在第 24 行的 /home/barbu/blog/admin/index.php 中获取 mysqli

如果我不关闭第一个连接(假设我让 ['unset($db)']),我的查询将在第一个数据库 ['siteinfo'] 上执行,我得到另一条错误消息,即告诉我“siteinfo”数据库中不存在“postInfo”表,这是真的。如果我让该连接保持不变,并声明另一个数据库类实例 $db1 和另一个 mysqli 对象 $mysqli1,它保存我的连接,并通过它执行我的查询,我得到与第二种情况相同的 mysqli 错误消息:“siteinfo.postInfo”不存在。你有什么建议我?我该如何解决这个问题?

【问题讨论】:

  • 警告:当使用mysqli 时,您应该使用parameterized queriesbind_param 将用户数据添加到您的查询中。 请勿使用字符串插值或连接来完成此操作,因为您创建了一个严重的SQL injection bug切勿$_POST$_GET 数据直接放入查询中,如果有人试图利用您的错误,这可能会非常有害。
  • 当有几个一流的 ORM 时,您有什么理由编写自己的 ORM 吗?强烈建议您使用DoctrinePropel,然后再将自己挖得太深。
  • @tadman:我没有听说过这两个库。我什至不知道 ORM 是什么意思。我会看看这两个并尝试熟悉它们。我认为这将使我更容易处理开始的数据库。谢谢你的回答!
  • 人们经常在不知道轮子存在的情况下重新发明轮子,这是一条合乎逻辑的路径。 ORM 使与数据库的交互更容易,并且大多数都为您提供了对架构进行正式更改的方法,从而使部署这些更改更容易管理。希望他们有所帮助!
  • 是的,我知道。其实我自己会尝试打破它。我想成为第一个。

标签: php mysql database mysqli


【解决方案1】:

首先,如果您希望每个会话只有一个连接并且不允许创建第二个实例,您应该将Database::__construct 定义为私有。 然后添加一个新方法Database::close。此方法的想法是关闭连接并将指向类数据库实例的链接设置为空。代码将如下所示:

public function close() 
{
   if (self::$_instance) {
       self::$_instance->getConnection()->close();
       self::$_instance = null;
   }
}

最后一点,你应该调用$db->close();而不是$mysqli->close();

【讨论】:

  • 嗯,这就是答案!非常感谢,一切正常知道!另外,我为什么要定义 Database::__construct private 以便为我的班级获得这种行为?我不太明白。
  • 因为可以创建一个像 $db = new Database(); 这样的新实例。你想避免它。 @lulian
  • 哦,我明白了。当你创建一个对象的新实例时,会调用construct magic方法,因此将其定义为私有不会让该方法执行。
猜你喜欢
  • 2013-09-04
  • 2014-03-07
  • 1970-01-01
  • 1970-01-01
  • 2013-12-26
  • 1970-01-01
  • 2018-12-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多