2010-12-16 40 views
12

我正在嘗試編寫一個PHP函數。這很簡單。它只是查詢數據庫的準備好的語句,但我無法使其工作。我一直在接收錯誤的調用一個非對象的成員函數prepare()。這裏是代碼:調用成員函數prepare()非對象PHP幫助

$DBH = new mysqli("host", "test", "123456", "dbname"); 
function selectInfo($limit, $offset){ 
    $stmt = $DBH->prepare("SELECT * FROM information LIMIT ?,?"); 
    $stmt->bind_param("ii", $limit, $offset); 
    $stmt->execute(); 
    } 
selectInfo(); 

任何時候我調用函數我得到那個錯誤。有人可以幫忙嗎?

回答

43

這是一個作用域錯誤。你正在使$DBH成爲一個全局變量。所以當你輸入函數時,全局變量不可用。你有5個真正的選擇。

1.使用global關鍵字

function doSomething() { 
    global $DBH; 
    //... 

這不是一個好主意,因爲它使得維護和測試PITA。想象一下,試圖調試該函數調用。現在,您需要去找出$DBH被定義爲揣摩這是怎麼回事...

2. $DBH參數傳遞給函數

function doSomething(MySQLi $DBH) { 

它具有無優勢明確。但它仍然不是很好,因爲調用代碼需要跟蹤全局變量。

3.創建一個函數來「獲得」 $DBH對象

function getDBH() { 
    static $DBH = null; 
    if (is_null($DBH)) { 
     $DBH = new mysqli(...); 
    } 
    return $DBH; 
} 

function doSomething() { 
    $DBH = getDBH(); 
} 

這有讓周圍的全局變量問題完全的優勢。但也很難有多個連接或重新使用任何其他連接的代碼。

4.創建一個類來包裝數據庫訪問

class Database { 
    public function __construct($host, $user, $pass) { 
     $this->DBH = new MySQli($host, $user, $pass); 
    } 
    public function doSOmething() { 
     $this->DBH->foo(); 
    } 
} 

此封裝你的一切。所有數據庫訪問將通過一個類,所以你不必擔心全局變量訪問或其他任何事情。

5.使用預建的類/框架

這是最好的選擇,因爲你不必擔心自己這樣做。

數據庫訪問類:

全框架:

真的,選擇是無止境的。找到你喜歡的東西,並堅持下去。它真的會讓你的生活更輕鬆...

祝你好運!

+1

+1不錯的選擇。 – 2010-12-16 17:35:55

+0

它沒有爲我工作:http://stackoverflow.com/questions/40080426/fatal-error-call-to-a-member-function-prepare-on-a-non-object-in-but-value – fresher 2016-10-17 12:35:53

3

嘗試在函數中添加global $DBH;,或將其添加到函數的參數中。

3
selectInfo($DBH); 

function selectInfo($DBH,$limit, $offset){ 
    $stmt = $DBH->prepare("SELECT * FROM information LIMIT ?,?"); 
    $stmt->bind_param("ii", $limit, $offset); 
    $stmt->execute(); 
    } 
7

$DBH不在範圍內。要麼你想在函數定義$DBH全球:

$DBH = new mysqli("host", "test", "123456", "dbname"); 
function selectInfo($limit, $offset){ 
    global $DBH; 
    $stmt = $DBH->prepare("SELECT * FROM information LIMIT ?,?"); 
    $stmt->bind_param("ii", $limit, $offset); 
    $stmt->execute(); 
} 

或ircmaxell在他的出色答卷指出,有它返回的$DBH靜態實例的功能。

+0

謝謝。我如何讓這個全球化並保持安全?我將連接包裝在一個函數中,然後爲它分配一個變量,如函數connect(){new myqsli(「host」,「test」,「123456」,「dbname」)} $ DBH = new connect(); (連接變量實際上隱藏在另一個文件中。) – mcbeav 2010-12-16 17:19:49

+0

是的,我會做出某種功能並從那裏獲取連接。 – Jim 2010-12-16 17:22:38

+0

@ircmaxell完成。你當然是對的。爲每個方法調用建立一個新的連接是一個壞主意。 – Jim 2010-12-16 17:29:57

3

很簡單。 selectInfo()函數中不存在$DBH。在全局範圍中定義的變量在函數內不可見,反之亦然。在手冊頁上閱讀有關variables scope的更多信息。

如何解決?將該變量作爲函數的參數傳遞:

$dbh = new MySQLi(...); 

function selectInfo(MySQLi $dbh, $limit, $offset) { 
    $stmt = $dbh->prepare(...); 
    ... 
} 
3

確保連接成功。

$DBH = @new mysqli("host", "test", "123456", "dbname"); 

if ($DBH->connect_errno) { 
    die('Connect Error: ' . $DBH->connect_errno); 
} 

$DBH = @mysqli_connect("host", "test", "123456", "dbname"); 

if (!$DBH) { 
    die('Connect Error: ' . mysqli_connect_errno()); 
} 
0

做$胸徑全球是不是健康的...除非你可以讓你的$胸徑類保護,並將其設置爲null .. ,並用它 ..

0
class PDOconnect extends PDO{ 

保護$ CON =空值;

public function __construct(){ 
       try {  

        $this->con= new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD); //our new PDO Object 

         $this->con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);      
         $this->con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);      
         $this->con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
         echo "hi.. you are connected succcessfully..."; 
        } 
相關問題