-1

アプリケーションには次のクラスがあります。

    <?php

    class Connection extends Mysqli{

public function __construct($mysqli_host,$mysqli_user,$mysqli_pass, $mysqli_db) {
    parent::__construct($mysqli_host,$mysqli_user,$mysqli_pass,$mysqli_db);
    $this->throwConnectionExceptionOnConnectionError();     
}

private function throwConnectionExceptionOnConnectionError(){

    if(!$this->connect_error){
        echo "Database connection established<br/>";
    }else{
    //$message = sprintf('(%s) %s', $this->connect_errno, $this->connect_error);
        echo "Error connecting to the database."; 
    throw new DatabaseException($message);
    }
}
    }

    class DatabaseException extends Exception
    {
    }

class Page extends Mysqli{

private $con; 

public function __construct(Connection $con) {
    $this->con = $con;
    if(isset($_GET['id'])){
    $id = $_GET['id'];
    }else{      
    $id = 1;
    }       
    $this->get_headers($id);
    $this->get_content($id);
    $this->get_footer($id);
}

private function get_headers($pageId){ 
    $retrieveHead = $this->con->prepare("SELECT headers FROM pages WHERE page_id=?");
    $retrieveHead->bind_param('i',$pageId);
    $retrieveHead->execute();
    $retrieveHead->bind_result($header);
    $retrieveHead->fetch();
    $retrieveHead->close();
    echo $header;   
}

private function get_footer($pageId){ 
    $retrieveFooter = $this->con->prepare("SELECT footer FROM pages WHERE page_id=?");
    $retrieveFooter->bind_param('i',$pageId);
    $retrieveFooter->execute();
    $retrieveFooter->bind_result($footer);
    $retrieveFooter->fetch();
    $retrieveFooter->close();
    echo $footer;   
}

private function get_content($pageId){
    $retreiveContent = $this->con->prepare("SELECT template_id, section_title, i1, i2 FROM content WHERE page_id=? ORDER BY sequence DESC");
    $retreiveContent->bind_param('i',$pageId);
    $retreiveContent->execute();
    $retreiveContent->bind_result($template_id, $section_title, $i1, $i2);
         while ($retreiveContent->fetch()) {
            //Variables will be populated for this row.
            //Update the tags in the template.
            $template = $this->get_template($template_id);
            $template = str_replace('[i1]',$i1,$template);
            $template = str_replace('[i2]',$i2,$template);
            //$theTemplate is populated with content. Probably want to echo here
            echo $template;
        }
}

private function get_template($template_id){
    $retreiveTemplate = $this->con->prepare("SELECT code FROM templates WHERE template_id=?");
    $retreiveTemplate->bind_param('i',$template_id);
    $retreiveTemplate->execute();
    $retreiveTemplate->bind_result($template);
    $retreiveTemplate->fetch();
    $retreiveTemplate->close();
    return $template;
}

}
    ?>       

小さなアプリケーションは基本的にURLからページ変数を取得し、それを使用してページのヘッダー、コンテンツアイテム、フッターを引き出し、コンテンツアイテムはデータベースからも取得されるテンプレートを使用してレンダリングされます。次のコードを含むインデックスファイルを実行する場合:

    require ("/req/db_connection.php");
    require ("/req/connection.php");
    $dbConnection = new Connection($mysqli_host,$mysqli_user,$mysqli_pass, $mysqli_db);
    $page = new Page();

次の出力が得られます。

    Database connection established

    Warning: mysqli::prepare(): Couldn't fetch Page in C:\xampp\htdocs\forum\req\connection.php on line 39

    Fatal error: Call to a member function bind_param() on a non-object in C:\xampp\htdocs\forum\req\connection.php on line 40

なぜ私がこれらのエラーを経験しているのかについて、誰かが正しい方向を示すことができますか?

39行目は次のステートメントです。

     $retrieveHead = $this->prepare("SELECT headers FROM pages WHERE page_id=?");

そしてもちろん40行目は次のとおりです。

     $retrieveHead->bind_param('i',$pageId);

どんな助けでも大歓迎です。

注意:上記のコードは以下の回答に基づいて修正されましたが、80行目でまだ次のエラーが発生しています。

    Call to a member function bind_param() on a non-object in C:\xampp\htdocs\forum\req\connection.php on line 80

この行はどれですか:

    $retreiveTemplate->bind_param('i',$template_id);

助言がありますか?

4

2 に答える 2

3
class Page extends Mysqli{
public function __construct() {
    if(isset($_GET['id'])){
    $id = $_GET['id'];
    }else{      
    $id = 1;
    }       
    $this->get_headers($id);
    $this->get_content($id);
    $this->get_footer($id);
}

上記のこのコードは(とりわけ)問題のように見えます。mysqliを拡張し、コンストラクターをオーバーライドして、親コンストラクターを呼び出さないでください。その結果、基本のmysqliコンストラクター・ルーチンは呼び出されず、接続が失われます。Connectionmysqliをどこにでも拡張するのではなく、オブジェクトを再設計してオブジェクトに渡すことを検討してください。また、コンストラクターですべての作業を行わないようにします。たとえば、ページクラスは次のようになります。

class Page{

private $con;

public function __construct(Connection $con) {
    $this->con = $con;
}

public function get_headers($pageId){ 
    $retrieveHead = $this->conn->prepare("SELECT headers FROM pages WHERE page_id=?");
    //...
}

}

上記の「とりわけ」(落胆を意図したものではありません)を装備したとき、エラーの実際の原因はコンストラクターでしたが、クラスの設計と一般的なOOPの概念に混乱があるように思われることをほのめかしていました。

class Connection extends Mysqli{

 public function __construct($mysqli_host,$mysqli_user,$mysqli_pass, $mysqli_db) {
    parent::__construct($mysqli_host,$mysqli_user,$mysqli_pass,$mysqli_db);
    $this->throwConnectionExceptionOnConnectionError();     
 }
}

ここでは、クラスを拡張mysqliConnection、親コンストラクターを正しく呼び出し、接続を確立するために必要なすべてのパラメーターを渡しました。このタイプのオブジェクトをインスタンス化する$myConnection = new Connection(...)と、データベースへのゲートウェイとして機能できます。

のような他のクラスPageは、データベースで操作を実行する必要がある場合があり、それ自体Connectionを拡張するのではなく、それを介して実行できますmysqliConnectionこれを実現するために、Pageコンストラクターでのインスタンスを渡すことができます。したがって、ここにあるコード行は次のとおりです。

$dbConnection = new Connection($mysqli_host,$mysqli_user,$mysqli_pass, $mysqli_db);
$page = new Page();

(上記のようにPageクラスにいくつかの変更を加えた後)次のようになります。

$dbConnection = new Connection($mysqli_host,$mysqli_user,$mysqli_pass, $mysqli_db);
$page = new Page($dbConnection);
于 2013-02-05T10:37:03.673 に答える
1

このエラーメッセージは、ステートメントを準備しようとしたときにデータベースサーバーへの接続が確立されていないために表示されます。短い再現コード:

class Page extends Mysqli{
    public function __construct(){
        $this->prepare('SELECT CURRENT_TIMESTAMP');
    }
}
new Page;

mysqlオブジェクトでは、接続はコンストラクターで確立されますが、そのようなコンストラクターをオーバーライドし、親コンストラクターを呼び出すことはありません。

私見ですが、ページがデータベースオブジェクトのインスタンスであることはほとんど意味がありません。必要に応じて、パラメータとしてDBオブジェクトを指定するだけです。

アップデート:

DBオブジェクトは、必要なときにいつでも渡すことができます。

class Page{
    public function foo(Mysqli $db){
        $db->prepare('SELECT CURRENT_TIMESTAMP');
    }
}

...または後で使用するために保存します。

class Page{
    protected $db;
    public function __construct(Mysqli $db){
        $this->db = $db;
    }
    public function foo(){
        $this->db->prepare('SELECT CURRENT_TIMESTAMP');
    }
}

拡張する場合Mysqliは、正しいクラス名をタイプヒントとして使用してください。

public function foo(Connection $db){
}

インターフェイスのような他のソリューションもありますが、複雑になりすぎます:)

于 2013-02-05T10:40:07.077 に答える