2016-08-30 20 views
0

このエラーが発生した場合は、私の問題を解決しようとしているので、私が見たこととは異なります。私は自分自身のインスタンスを1つしか作成せず、mysqlサーバーへの接続数を1に制限しようとするクラス、データベースを持っています。ここで[コード1]私のクラスである:PHPがデータベースへのmysqli接続エラーを終了する

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; 
     } 
    } 

このクラスの後、私はテーブルからいくつかの情報を取得するための接続を作成しました。コードは以下の[コード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']; 
    } 

、別のファイルでは、私はこの[コード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); 

を、私はエラーを取得します:

Warning: mysqli::query(): Couldn't fetch mysqli in /home/barbu/blog/admin/index.php on line 24

私は最初の接続を閉じて(と私はちょうど[「解除($デシベル)」]聞かせましょう)していない場合は、私のクエリはモミ上で実行されます私は、 'postinfo'テーブルが 'siteinfo'データベースに存在しないことを伝えています。これは本当です。私がその接続を持続させ、データベースクラス$ db1と別のmysqliオブジェクト$ mysqli1を宣言し、それを介して私のクエリを実行すると、私は同じmysqliエラーメッセージを2番目のケースと同じにします: 'siteinfo.postInfo'は存在しません。あなたは私に何を勧めますか?どうすればこの問題を解決できますか?

+0

を呼び出す必要があります。** WARNING **:あなたは、[パラメータ化クエリ]を使用する必要がありmysqli' '使用する場合(のhttp:/コードは次のようになります。 /php.net/manual/en/mysqli.quickstart.prepared-statements.php)と['bind_param'](http://php.net/manual/en/mysqli-stmt.bind-param.php)を追加しますユーザーデータをクエリに追加します。 **重大な[SQLインジェクションのバグ](http://bobby-tables.com/)を作成したため、文字列の補間または連結を使用してこれを実行しないでください。 ** '$ _POST'や' $ _GET'データを直接クエリに入れないでください。誰かがあなたのミスを悪用しようとすると、非常に危険です。 – tadman

+0

そこにいくつかのファーストクラスのものがあるときにあなた自身のORMを書いている理由はありますか?ここに穴をあけすぎる前に[Doctrine](http://www.doctrine-project.org/)や[Propel](http://propelorm.org/)を使うことを強くお勧めします。 – tadman

+0

@tadman:私はこれらの2つのライブラリについて聞いていませんでした。私はORMが何を意味するのかも知らなかった。私はその2つを見て、それらに慣れてみましょう。私はそれが最初のデータベースで扱いやすくなると思う。あなたの答えをありがとう! –

答えて

0

最初に、セッションごとに1つの接続しか持たず、セカンドインスタンスを作成できないようにするには、Database::__constructをプライベートとして定義する必要があります。 次に、新しいメソッドDatabase::closeを追加します。このメソッドのアイデアは、接続を閉じ、クラスDatabaseのインスタンスへのリンクをnullに設定することです。

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

決勝点、代わりの$mysqli->close();あなたは$db->close();

+0

それは答えです!どうもありがとう、すべての作品は知っている!また、なぜ私のクラスの動作を取得するために、Database :: __ construct privateを定義する必要がありますか?私はそれをかなり理解していませんでした。 –

+0

$ db = new Database();のような新しいインスタンスを作成することができます。あなたはそれを避けたいです。 @lulian –

+0

ああ、そうだ。オブジェクトの新しいインスタンスを作成するときには、魔法のメソッドが呼び出されるので、それをprivateとして定義してもメソッドは実行されません。 –

関連する問題