2016-05-24 57 views
1

我創建了自己的數據庫類來簡化MySQLi預準備語句,並試圖在另一個類中訪問它。從另一個類訪問數據庫類

我已經數據庫類延伸到我的個人資料類,並試圖在我的構建中運行SELECT查詢並返回此錯誤:

Fatal error: Call to a member function prepare() on null in /home/matt500b/dev2.csgoberry.com/includes/database.class.php on line 80

配置文件類結構:

public function __construct($username) { 
    $params = parent::SELECT("SELECT users_info.*, users.username, users.lastOnline FROM users_info INNER JOIN users ON users.id = users_info.user_id WHERE users.username = ?", array('s', $username)); 
    $this->fname = (isset($params[0]['fname']) ? $params[0]['fname'] : null); 
    /*More settings done here*/ 
} 

但是,如果我首先運行查詢,然後將數據發送到構造如下:

$profileData = $db->SELECT('SELECT users_info.*, users.username, users.lastOnline FROM users_info INNER JOIN users ON users.id = users_info.user_id WHERE users.username = ?', array('s', $pid)); 
$pclass = new user_profile($profileData); 

與構造是:

public function __construct($params){ 
     $this->fname = (isset($params[0]['fname']) ? $params[0]['fname'] : null); 
} 

一切工作很好。

public function __construct($db_host, $db_user, $db_pass, $db_name, $debug){ 
    $this->link = mysqli_connect($db_host, $db_user, $db_pass); 
    mysqli_select_db($this->link, $db_name); 
    $this->debug = $debug; 
} 

錯誤涉及到這一行:if ($stmt = $this->link->prepare($sql)) {並建議$ SQL是空但是這兩個查詢是完全相同,除了他們的起源是相同的(當然,數據庫實例使用$db = new database(HOST, USER, PASSWORD, DATABASE, DEBUG);在我的數據庫結構是所謂的parent::SELECT vs $db->SELECT)。

任何建議,使其工作?

非常感謝

+0

'$這個 - > link'爲空不'$ sql'。我不會在問題的代碼示例中看到這行代碼。你的問題非常難以理解,因爲不清楚整個調用堆棧是什麼樣的。 –

+0

$ this-> link是在數據庫結構中定義的。 – Matt

回答

2

當你擴展一個類,無論是父母與子女類有一個構造函數,則必須調用從孩子的父類的構造。如果父構造函數有參數,則必須a)在子構造函數中獲取這些參數(最佳實踐),或者b)使用硬編碼值(通常是不好的練習)。

我假設:a)您的父類在其構造函數中建立數據庫連接,或者b)將數據庫連接傳遞給父類。如果是後者(b),那麼必須將該db連接作爲子類的參數並手動調用父構造函數OR,則需要從子類中的父構造函數重新實現任務。如果前者,(a),以上是真實的,但是你參與了一個不好的練習。一個類的構造函數不應該工作,它不應該知道其他類,除了它的祖先和類型化的構造函數參數。在構造函數體中new關鍵字通常是一個「代碼味道」的標誌 - 您創建一個隱藏的依賴

取而代之的是一類使用數據庫:

public function __construct ($username, $password) { 
    // establish database connection using username and password 
} 

.... 

$myObject = new SomeClass('ausername', 'apassword'); 

。 ..做到這一點:

$dbConnection = establishDbConnection($username, $password); // establish connection outside of the class 
$myObject = new SomeClass($dbConnection); // pass in the connection into the object 

^這就是所謂的「依賴注入」,是一個值得學習的話題!

這裏是調用父類的構造的一個例子:

class A { 
    private $a1 = null; 
    public function __construct($arg1) { 
     // do something with the args 
     $this->a1 = $arg1; 
    } 
} 

class B extends A { 
    private $a2 = null; 
    public function __construct($arg1, $arg2) { 
     parent::__construct($arg1); 
     $this->a2 = $arg2; 
    } 
} 

文檔

+0

所以當我創建一個新的b實例時,我需要做類似'$ myVar = new b($ classAParams,$ classParams);'並且在類A的構造函數中使用classAParams? – Matt

+0

@Matt確實,是的,儘管如果A類在其構造函數中建立了一個數據庫連接,請查看我的註釋(編輯該帖子)......不是很好的做法。 –

+0

在我的db類中,我使用'$ db = new database(HOST,USER,PASSWORD,DATABASE,DEBUG);'(你可以在我的問題中看到db結構)創建一個新實例。你是說最好將'$ db'的值傳遞給classB,而不是將class A的參數傳遞給class B?如果是這樣的話,我將如何繞過將'$ db'發送給B,以便我可以使用數據庫類,從而不需要使用classA構造? – Matt