簡體   English   中英

如何使用mysqli准備好的語句?

[英]How to use mysqli prepared statements?

我正在嘗試准備好的語句,但下面的代碼不起作用。 我收到錯誤消息:

致命錯誤:在第 12 行的 /var/www/prepared.php 中的非對象上調用成員函數 execute()

<?php

    $mysqli = new mysqli("localhost", "root", "root", "test");
    if ($mysqli->connect_errno) {
        echo "Failed to connect to MySQL: " . $mysqli->connect_error;
    }

    $stmt = $mysqli->prepare("INSERT INTO users (name, age) VALUES (?,?)");

    // insert one row
    $stmt->execute(array('one',1));

    // insert another row with different values
    $stmt->execute(array('two',1));
?>

另外,我需要對准備好的語句使用 mysqli 嗎? 誰能給我一個完整的例子,從連接到插入到選擇錯誤處理的准備好的語句?

來自mysqli::prepare文檔

在執行語句或獲取行之前,必須使用 mysqli_stmt_bind_param() 和/或 mysqli_stmt_bind_result() 將參數標記綁定到應用程序變量。

bind_param文檔

IE:

$name = 'one';
$age  = 1;

$stmt = $mysqli->prepare("INSERT INTO users (name, age) VALUES (?,?)");

// bind parameters. I'm guessing 'string' & 'integer', but read documentation.
$stmt->bind_param('si', $name, $age);

// *now* we can execute
$stmt->execute();

我還需要為准備好的語句使用 mysqli。 任何人都可以指出一個完整的例子,從連接到插入到選擇與錯誤處理的准備好的語句

你也可以使用我更喜歡的 PDO。 事實上,看起來您在代碼示例中混淆了 PDO 和 Mysqli。

$db = new PDO($dsn, $user, $pass);
$stmt = $db->prepare("INSERT INTO users (name, age) VALUES (?,?)");
$stmt->execute(array($name1, $age1));
$stmt->execute(array($name2, $age2));

與 mysqli 不同,您不必調用單獨的綁定函數,盡管如果您喜歡/想要/需要使用它,該功能是可用的。

PDO 的另一個有趣之處是命名占位符,它在復雜查詢中可以減少混淆:

$db = new PDO($dsn, $user, $pass);
$stmt = $db->prepare("INSERT INTO users (name, age) VALUES (:name,:age)");
$stmt->execute(array(':name' => $name1, ':age' => $age1));
$stmt->execute(array(':name' => $name2, ':age' => $age2));

聯系

mysqli 連接的重要性經常被忽視,被貶低為單行。 而正確的連接代碼可以解決許多問題,從安全性到可用性。

鑒於您的代碼是通常的 PHP 程序,這里有一個簡單的 mysqli 連接代碼將包含在您的腳本中:

$host = '127.0.0.1';
$db   = 'test';
$user = 'root';
$pass = '';
$charset = 'utf8mb4';

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
    $mysqli = new mysqli($host, $user, $pass, $db);
    $mysqli->set_charset($charset);
} catch (\mysqli_sql_exception $e) {
     throw new \mysqli_sql_exception($e->getMessage(), $e->getCode());
}
unset($host, $db, $user, $pass, $charset); // we don't need them anymore

完整的解釋可以在我的文章如何使用 mysqli 正確連接(以及許多有用的提示)中找到,但只是一個小引用來突出最重要的部分:

  • 為連接設置正確的字符集將消除整類錯誤,例如奇怪的字符/問號而不是您的數據、空的 json_encode() 輸出、存儲表情符號的問題等。
  • 設置正確的錯誤報告模式將消除神秘的錯誤消息,如 mysqli_fetch_assoc() 需要參數.../調用成員函數 bind_param()...,而是為您提供來自 MySQL 的實際錯誤消息。
  • 安全不是笑話,不應該有機會將您的數據庫詳細信息泄露給外界

插入

插入查詢比較簡單,其他答案中已經介紹過了。

您只需要用問號替換查詢中的所有變量(以及周圍的引號!),然后准備查詢,然后將所有變量及其類型推入bind_param()並最終執行查詢。

只是一個快速提示:MySQL 很樂意接受所有變量作為字符串,所以不要為某個變量尋找正確的類型,只需使用“s”即可。

所以基本上插入是這樣的

$sql = "INSERT INTO users (name, email, password) VALUES (?,?,?)";
$stmt= $conn->prepare($sql);
$stmt->bind_param("sss", $name, $email, $password_hash);
$stmt->execute();

對於所有其他查詢類型,例如 UPDATE 或 DELETE,應使用相同的原則。

選擇

運行選擇查詢幾乎相同,但有一個小技巧。 由於某些未知的原因,您不能在准備好的語句中使用熟悉的 fetch 函數。 因此,您需要先獲取mysqli_result ,然后才能使用fetch_assoc()fetch_obj()等:

$sql = "SELECT * FROM users WHERE id=?"; // SQL with parameters
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $id);
$stmt->execute();
$result = $stmt->get_result(); // get the mysqli result
$user = $result->fetch_assoc(); // fetch data 

提示:絕對不需要熟悉的mysqli_num_rows()函數。 如果您想到它,您可以隨時使用數據本身來查看您的查詢是否返回了任何行:

$user = $result->fetch_assoc();
if ($user) {
    // found!
}

多行也是如此,這要歸功於

另一個提示:有一個方便的函數fetch_all()可以一次性獲取所有選定行的數組。 例如,如果查詢返回多行,您可以通過將最后一行更改為

$users = $result->fetch_all(MYSQLI_ASSOC); // fetch data 

錯誤處理

錯誤處理是最重要但又有些令人驚訝的部分。 盡管有很多文章和示例都說了,但作為一項規則,您根本不應該編寫任何錯誤處理代碼 這聽起來絕對是瘋狂的,但這正是事情必須要做的事情。 大多數時候,您需要做的只是報告錯誤。 並且 mysqli/PHP 已經可以為您完成,無需幫助。 因此,您不應該編寫任何代碼來驗證查詢執行結果——如果出現錯誤,mysqli 會自動報告它,這要歸功於#Connection 部分中提到的mysqli_report()函數調用。 同樣,可以在另一篇專門針對一般PHP 錯誤報告的文章中找到對該原理的完整解釋。

在極少數情況下,您確實需要處理錯誤,即在發生錯誤時執行一些操作而不是僅僅報告錯誤,然后將您的查詢包裝在try..catch中。

試試這個,清理傳入的數據。 並且不要忘記 php 標簽。

function clean($data)
{ 
  $data = trim(strip_tags(htmlspecialchars($data)));
  return $data;
}

$field1 = isset($_POST['field1']) ? clean($_POST['field1']): NULL;
$field2 = isset($_POST['field2']) ? clean($_POST['field2']): NULL;
$field3 = isset($_POST['field3']) ? clean($_POST['field3']): NULL;
$field4 = isset($_POST['field4']) ? clean($_POST['field4']): NULL;
$field5 = isset($_POST['field5']) ? clean($_POST['field5']): NULL;
$field6 = isset($_POST['field6']) ? clean($_POST['field6']): NULL;
$field7 = isset($_POST['field7']) ? clean($_POST['field7']): NULL;
$database = new mysqli("localhost", "username", "password", "database");
if ($database->errno) die("Error opening database: " . $database->error());
$query = 'INSERT INTO `tablename` (`field1`, `field2`, `field3`, `field4`, `field5`, `field6`, `field7`) VALUES (?, ?, ?, ?, ?, ?, ?)'; 
$result = $database->prepare($query); 
$result->bind_param('sssssss', $field1, $field2, $field3, $field4, $field5, $field6, $field7); 
$result->execute(); 
$database->close();
{
    header("Location: http://www.somewebsite.com");
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM