PHP中的MySQLi擴充套件學習(二)mysqli類的一些少見的屬性方法

Jack2k發表於2021-09-09

雖說是少見的一些屬性方法,但是可能還是有不少同學在日常的開發中使用過,這裡只是學習了可能相對來說我們用得比較少的一些 mysqli 的屬性或方法。就當是擴充套件一下自己的知識體系。

切換使用者

首先就是切換一下當前連線資料庫的使用者。

// 切換使用者
$mysqli->change_user('root2', "123", 'blog_test');

// 錯誤資訊
$res = $mysqli->query( "SELECT * FROM zyblog_test_user");
var_dump($res); // bool(false)

var_dump($mysqli->error_list);
// array(1) {
//     [0]=>
//     array(3) {
//       ["errno"]=>
//       int(1142)
//       ["sqlstate"]=>
//       string(5) "42000"
//       ["error"]=>
//       string(78) "SELECT command denied to user 'root2'@'localhost' for table 'zyblog_test_user'"
//     }
//   }

使用 change_user() 方法就能夠方便地在 mysqli 物件已經例項化之後再來進行使用者的切換。在這段程式碼中,我們的 root2 使用者沒有 blog_test 表的 SELECT 許可權,所以返回的 query() 查詢結果是空的。透過列印 mysqli 的 error_list 屬性就可以看到當前的錯誤資訊。

錯誤資訊

緊接著上一段,對於執行語句的錯誤資訊,我們可以透過幾個 mysqli 中的屬性來獲得。比如上文中的 error_list 。它裡面包含的就是所有的錯誤資訊列表,並且是非常詳細的錯誤資訊內容。不過我們還可以透過另外兩個屬性來獲得單獨的錯誤號和錯誤資訊的字串。

var_dump($mysqli->errno); // int(1142)
var_dump($mysqli->error); // string(78) "SELECT command denied to user 'root2'@'localhost' for table 'zyblog_test_user'"

errno 屬性裡面儲存的就是資料庫的錯誤號,error 屬性中儲存的是錯誤資訊的詳細文字說明。這兩個錯誤資訊內容都是在執行 SQL 語句之後資料庫返回的內容。

連線錯誤資訊

當然,如果在連線資料庫的時候就產生了錯誤,我們也可以透過 connect_errno 和 connect_error 來獲得它們的錯誤號和錯誤資訊內容。

$mysqli2 = @new mysqli("xxx", "root", "", "blog_test");
var_dump($mysqli2->connect_errno); // int(2002)
var_dump($mysqli2->connect_error); // string(90) "php_network_getaddresses: getaddrinfo failed: nodename nor servname provided, or not known"

在這段程式碼中,我們使用了錯誤的 host 資訊。如果不在例項化的時候加上錯誤抑制符,那麼在例項化的時候就會報出 PHP 的警告資訊 Warning 。在這裡我們為了測試輸出的清晰,加上了錯誤抑制符。

客戶端連線的統計資料

var_dump($mysqli->get_connection_stats());
// array(163) {
//     ["bytes_sent"]=>
//     string(3) "306"
//     ["bytes_received"]=>
//     string(3) "287"
//     ["packets_sent"]=>
//     string(2) "10"
//     ["packets_received"]=>
//     string(1) "6"
//     ["protocol_overhead_in"]=>
//     string(2) "24"
//     ["protocol_overhead_out"]=>
//     string(2) "40"
//     ["bytes_received_ok_packet"]=>
//     string(1) "0"
//     ["bytes_received_eof_packet"]=>
//     string(1) "0"
//     ……
//     ……
//     ["bytes_received_real_data_normal"]=>
//     string(1) "0"
//     ["bytes_received_real_data_ps"]=>
//     string(1) "0"
//   }

透過 get_connection_stats() 方法,我們可以獲得當前資料庫連線的一些統計資訊。返回的內容非常多,官方也沒有具體的每個欄位的說明文件。不過從欄位名中我們還是可以看到一些有用的資訊,比如 bytes_sent 位元組傳送的數量,bytes_received 位元組接收的數量。

字符集

最近這些年,我們使用 PHP + MySQL 開發基本上都已經是統一地在使用 UTF-8 來作為預設的字符集編碼了。不過在早些時候,包括 Discuz 、 DedeCMS 這些早期的開源建站程式都會提供一套 UTF-8 和一套 GBK 的原始碼供大家使用。而 mysqli 則可以方便快捷地獲取及切換當前資料庫所使用的字符集。

獲取資料庫字元

// 獲取資料庫字元
var_dump($mysqli->character_set_name()); // string(4) "utf8"

character_set_name() 不要以為看到一個 set 關鍵字就是設定或者修改什麼,這個方法是獲取當前的字符集資訊的。

字符集詳細資訊

var_dump($mysqli->get_charset());
// object(stdClass)#2 (8) {
//     ["charset"]=>
//     string(4) "utf8"
//     ["collation"]=>
//     string(15) "utf8_general_ci"
//     ["dir"]=>
//     string(0) ""
//     ["min_length"]=>
//     int(1)
//     ["max_length"]=>
//     int(3)
//     ["number"]=>
//     int(33)
//     ["state"]=>
//     int(1)
//     ["comment"]=>
//     string(13) "UTF-8 Unicode"
//   }

我們也可以透過 get_charset() 獲取當前資料庫連線的詳細字符集資訊。其中 charset 就是字元型別,我們這裡是 UTF-8 型別的,字符集是 utf8_general_ci ,這一套基本上就是我們現在開發時的標配了。

設定字符集

$mysqli->set_charset('gbk');
$mysqli->query("insert into zyblog_test_user(username, password, salt) values('GBK字元','dd','d')");
var_dump($mysqli->error); // string(65) "Incorrect string value: 'xACxA6' for column 'username' at row 1"

$mysqli->set_charset('utf8');
$mysqli->query("insert into zyblog_test_user(username, password, salt) values('UTF字元','dd','d')");
var_dump($mysqli->error);
echo $mysqli->insert_id, PHP_EOL;

透過 set_charset() 方法就可以設定當前資料庫連線的字元。在第一段程式碼中我們將連線字元設定為 gbk ,然後執行插入語句,直接就會返回字元不匹配的資訊了。

特殊字元轉義

既然說到字元的問題了,我們順便多提一句關於 SQL 注入的問題。除了使用 預處理 功能來解決 SQL 注入之外,MySQLi 還為我們提供了一個 real_escape_string() 方法,可以手工地解決SQL語句中的一些特殊符號問題。

$username = "aaa ' bbb";
$username = $mysqli->real_escape_string($username);
var_dump($username); // string(10) "aaa ' bbb"

使用這個方法可以說和 addslashes() 方法類似,不過它比 addslashes() 方法轉義的內容更多一些,它包括: NUL (ASCII 0),n,r,,’," 和 Control-Z 這些字元。

執行緒操作

關於 MySQL 的執行緒問題,我們將來在深入學習並且刷 MySQL 文件的時候再說(因為現在我也不是很清楚~~)。在這裡,我們就先看看 mysqli 中關於 MySQL 執行緒的幾個屬性和方法吧。

var_dump($mysqli->thread_safe); // NULL

var_dump($mysqli->thread_id); // int(600)


$thread_id = $mysqli->thread_id;
$mysqli->kill($thread_id);

if (!$mysqli->query("insert into zyblog_test_user(username, password, salt) values('kill執行緒了','dd','d')")) {
    var_dump($mysqli->error); // string(26) "MySQL server has gone away"
}

thread_safe 屬性是儲存的當前資料庫連線是否是執行緒安全的,在我們的測試中返回的是 NULL 而不是正常的布林值,這一塊將來我們學習到了再說。thread_id 屬性儲存的是當前連線的執行緒ID,透過這個執行緒ID,我們就可以使用另外一個 kill() 方法來殺死當前的執行緒。其實就相當於關閉了當前這個 mysqli 物件的連線,這時我們再使用這個連線物件進行其它操作時就會出現 MySQL server has gone away 的提示資訊了。

mysqli 物件

上面說的很多屬性其實我們可以直接透過列印 mysqli 物件就可以檢視到。

var_dump($mysqli);
// object(mysqli)#1 (19) {
//     ["affected_rows"]=>
//     int(1)
//     ["client_info"]=>
//     string(79) "mysqlnd 5.0.12-dev - 20150407 - $Id: 7cc7cc96e675f6d72e5cf0f267f48e167c2abb23 $"
//     ["client_version"]=>
//     int(50012)
//     ["connect_errno"]=>
//     int(2002)
//     ["connect_error"]=>
//     string(90) "php_network_getaddresses: getaddrinfo failed: nodename nor servname provided, or not known"
//     ["errno"]=>
//     int(0)
//     ["error"]=>
//     string(0) ""
//     ["error_list"]=>
//     array(0) {
//     }
//     ["field_count"]=>
//     int(0)
//     ["host_info"]=>
//     string(25) "Localhost via UNIX socket"
//     ["info"]=>
//     NULL
//     ["insert_id"]=>
//     int(59)
//     ["server_info"]=>
//     string(6) "8.0.17"
//     ["server_version"]=>
//     int(80017)
//     ["stat"]=>
//     string(139) "Uptime: 355128  Threads: 4  Questions: 35696  Slow queries: 0  Opens: 764  Flush tables: 3  Open tables: 636  Queries per second avg: 0.100"
//     ["sqlstate"]=>
//     string(5) "00000"
//     ["protocol_version"]=>
//     int(10)
//     ["thread_id"]=>
//     int(606)
//     ["warning_count"]=>
//     int(0)
//   }

像是 host_info 顯示的是我們連線資料庫的 host 資訊,server_info 是連線到的資料庫的版本資訊,就像我們這裡使用的是 MySQL8 。stat 簡單的統計資訊,裡面能看到有 4 個執行緒,沒有慢查詢等等。大家可以仔細地研究一下這個物件中的這些屬性,或許某些內容就是你在實際專案中所需要的。

總結

今天的文章學習的就是一些簡單的 mysqli 類所持有的屬性和方法。我們還沒有正式開始學習查詢之類的語句,不過從這些屬性方法就可以看出,相對於 PDO 來說,mysqli 提供的功能確實更加的全面一些。後面我們將繼續深入地學習和探索 mysqli 的各種方法和使用。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/36/viewspace-2797110/,如需轉載,請註明出處,否則將追究法律責任。

相關文章