就像 PDO 中的 PDO_Statment 物件一樣,MySQLI_STMT 物件也是一個預處理陳述句所形成的物件,專門用來操作 MySQLi 所生成的預處理陳述句的,其實操作方式之類也都比較相似,不外乎以系結引數為主的一些針對 SQL 陳述句和獲取結果集的操作,
引數系結及操作屬性
之前的文章中想必大家已經見過我們使用的 bind_param() 方法,它與 PDO 中的 bindParam() 方法有很大的不同,
$stmt = $mysqli->prepare("insert into zyblog_test_user(username, password, salt) values(?, ?, ?)");
$username='mysqli_username';
$password='mysqli_password';
$salt = 'mysqli_salt';
$stmt->bind_param('sss', $username, $password, $salt);
var_dump($stmt->insert_id); // int(232)
var_dump($stmt->affected_rows); // int(1)
$stmt->execute();
$stmt->close();
首先就是之前提到過的,MySQLI_STMT 中系結引數只能使用 ? 問號占位符,然后在使用 bind_param() 時,使用的是 's' 這種來按順序系結引數,這個 's' 代表的就是字串,另外還可以是 'i' 表示整型數字、'd' 表示浮點數字、 'b' 表示 blob 型別,
另外,從上面的測驗代碼中還可以看出,可以使用一個 bind_param() 方法系結多個引數,'sss' 就是三個字串,按順序進行系結,
系結引數之后,我們就可以通過 execute() 方法來執行陳述句,同 PDO 一樣,這個方法只回傳成功失敗的資訊,也就是一個布林值,所以,我們需要通過 MySQLI_STMT 物件的 insert_id 來獲得新增加資料的 ID ,或者通過 affected_rows 屬性來獲得當前陳述句執行后影響的行數,來確定陳述句是否真正地執行完成并達到我們的期望,
最后,我們使用 close() 關閉一個當前的 STMT 物件,這樣在后面的操作中上面的 $stmt 物件就無法使用了,
接下來,我們看看如果系結了錯誤的型別會怎么樣,以及 MySQLI_STMT 中關于錯誤資訊的提示,
$stmt = $mysqli->prepare("insert into zyblog_test_user(id, username, password, salt) values(?, ?, ?, ?)");
$id = 's';
$username='mysqli_username';
$password='mysqli_password';
$salt = 'mysqli_salt';
$stmt->bind_param('isss', $username, $password, $salt);
$stmt->execute();
var_dump($stmt->errno); // int(2031)
var_dump($stmt->error); // string(53) "No data supplied for parameters in prepared statement"
var_dump($stmt->error_list);
// array(1) {
// [0]=>
// array(3) {
// ["errno"]=>
// int(2031)
// ["sqlstate"]=>
// string(5) "HY000"
// ["error"]=>
// string(53) "No data supplied for parameters in prepared statement"
// }
// }
$stmt->close();
在代碼中,我們增加了 id 引數的系結,然后指定的型別是 'i' ,但是,我們實際傳遞的變數是一個字串型別,結果就會導致 MySQLI_STMT 產生錯誤,
可以看出,MySQLI_STMT 的錯誤屬性和資訊基本和 MySQLi 物件的是一樣的,
列系結
除了請求查詢陳述句引數的系結之外,MySQLI_STMT 也是支持直接系結列的,就和 PDO 中的 bindColumn() 一樣,
$stmt = $mysqli->prepare("select * from zyblog_test_user where username = ?");
$username = 'kkk';
$stmt->bind_param("s", $username); // 系結引數
$stmt->bind_result($col1, $col2, $col3, $col4);
$stmt->execute(); // 執行陳述句
var_dump($stmt);
// object(mysqli_stmt)#2 (10) {
// ["affected_rows"]=>
// int(-1)
// ["insert_id"]=>
// int(0)
// ["num_rows"]=>
// int(0)
// ["param_count"]=>
// int(1)
// ["field_count"]=>
// int(4)
// ["errno"]=>
// int(0)
// ["error"]=>
// string(0) ""
// ["error_list"]=>
// array(0) {
// }
// ["sqlstate"]=>
// string(5) "00000"
// ["id"]=>
// int(3)
// }
while($stmt->fetch()){
printf("%s %s %s %s", $col1, $col2, $col3, $col4);
echo PHP_EOL;
}
// 42 kkk 666 k6
// 43 kkk 666 k6
// ……
var_dump($stmt->num_rows); // int(7)
$stmt->close();
當然,方法的名稱還是有些變動的,MySQLI_STMT 中系結列的方法名為 bind_result() ,雖說名字不一樣,但功能其實都是差不多的,查詢陳述句中是幾個列名,就要系結幾個列名,在這個表中,我們有四個欄位,所以通過參考傳遞的方式系結了 4 個列變數,當使用 fetch() 進行查詢結果物件的遍歷時,就像使用參考的方式為這 4 個列變數賦值,
在這段代碼中,我們使用了 num_rows 這個屬性來獲得查詢結果的行數量,這個屬性是只針對 SELECT 陳述句的,上面介紹過的 affected_rows 是受影響的行數,這兩個屬性不是相同的概念哦!
回傳結果集
執行 fetch() 方法回傳的是一個布林值,它主要的作用是將結果集系結到指定的變數中,所以如果你直接列印它的結果是不會有什么有用的資訊的,我們必須通過系結列變數的方式來獲得資料,而真正獲得結果集的資料其實是通過另一個方法來獲得一個 MySQLI_result 物件,然后再使用這個物件里面的方法就可以像 PDO 的 fetch() 一樣來獲得真正的結果集了,
$stmt = $mysqli->prepare("select * from zyblog_test_user where username = 'kkk'");
$stmt->execute(); // 執行陳述句
$result = $stmt->get_result();
while($row = $result->fetch_assoc()){
var_dump($row);
}
// array(4) {
// ["id"]=>
// int(42)
// ["username"]=>
// string(3) "kkk"
// ["password"]=>
// string(3) "666"
// ["salt"]=>
// string(2) "k6"
// }
// ……
$stmt->close();
在這里,我們通過 get_result() 方法獲得了一個結果集的 MySQLI_result 物件,然后通過該物件的 fetch_assoc() 就獲得了鍵名形式的結果集陣列,
關于 MySQLI_result 物件的內容,我們將在下篇文章中再進行詳細的學習了解,
保存結果集及游標移動
最后就是關于游標的移動,上面的測驗資料中我們可以查詢到 7 條資料,并且第一條資料的 id 是 42 ,通過游標,我們可以不在 SQL 陳述句中使用 limit 而直接操作結果集來獲取需要的資料,
$stmt = $mysqli->prepare("select * from zyblog_test_user where username = 'kkk'");
$stmt->bind_result($col1, $col2, $col3, $col4);
$stmt->execute(); // 執行陳述句
$stmt->store_result();
// 一共7條,從第5個開始
$stmt->data_seek(5);
$stmt->fetch();
printf("%s %s %s %s", $col1, $col2, $col3, $col4); // 47 kkk 666 k6
echo PHP_EOL;
$stmt->close();
首先,我們需要使用 store_result() 方法來將結果集保存到記憶體中,這個方法和 MySQLi 中的 store_result() 方法是一樣的,然后,通過 data_seek() 方法將游標移動 5 個位置,最后輸出的結果就是后面那兩條資料的內容了,是不是很高大上的感覺!
總結
關于 MySQLI_STMT 物件的內容還有一些,不過就不是那么常用了,從我們講解的這些內容也可以看出它和 PDO 的許多不同之處,當然,總體的大方向基本還是一致的,所以我們學習起來也并不會有太大的困難,掌握理解之后更多的還是要動手操作,基本功可千萬不能荒廢哦!
測驗代碼:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202009/source/8.PHP中的MySQLi擴展學習(五)MySQLI_STMT物件操作.php
參考檔案:
https://www.php.net/manual/zh/book.mysqli.php
關注公眾號:【硬核專案經理】獲取最新文章
添加微信/QQ好友:【xiaoyuezigonggong/149844827】免費得PHP、專案管理學習資料
知乎、公眾號、抖音、頭條搜索【硬核專案經理】
B站ID:482780532
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/288500.html
標籤:其他
