關於 PDO 的學習我們告一段落,從這篇文章開始,我們繼續學習另外一個 MySQL 擴展,也就是除了 PDO 之外的最核心的 MySQLi 擴展。可以說它的祖先,也就是 MySQL(原始) 擴展是我們很多人剛開始學習 PHP 時連接數據庫的入門導師。不過隨着時代的變遷,MySQL(原始) 擴展在 PHP7 中已經被徹底廢棄了。現在如果想要使用過程式的代碼來操作數據庫,只能使用 mysqli 擴展了。當然,mysqli 擴展也是支持面向對象式的寫法的。
什麼是 MySQLi
MySQLi 擴展允許我們訪問 MySQL4.1 及以上版本的數據庫所提供的功能。它是專門針對於 MySQL 數據庫的,不像 PDO 可以通過不同的 dns 來連接不同的數據庫。
與 MySQL 和 PDO 的區別與聯繫
首先,我們還是回顧一下最早的 MySQL 擴展。
只面向過程
不支持 存儲過程 、 多語句執行 、 預處理語句
PHP7 中已經刪除了並且完全不支持
然後是 PDO 。
僅支持面向對象方式使用
可以連接多種數據庫,切換數據庫帶來的變更少,甚至可能不用修改代碼
支持 存儲過程 、 多語句執行 、 預處理語句
最後就是 MySQLi 。
支持面向對象和麪向過程兩種寫法
僅支持 MySQL 數據庫
支持 存儲過程 、 多語句執行 、 預處理語句
跟隨 PHP 及 MySQL 的版本更新,可以更快速地支持更多的 MySQL 高級特性
從它們三個的這些特點來看,MySQL(原始)擴展肯定是不推薦了,就算是老的項目,只要是支持 PDO 或 MySQLi 的 PHP 版本,都應該考慮將數據庫的連接轉換成這兩種方式之一。如果你還在 PHP5 的環境中學習 MySQL(原始)擴展的使用的話,也可以放下了。
而對於 PDO 和 MySQLi 的選擇來說,就仁者見仁智者見智了。本身它們其實並沒有什麼太大的差別,不過現代化的大型框架中基本都會將 PDO 作爲默認的數據庫連接來進行封裝,畢竟它的可移植性可以方便這些通用框架連接不同的數據庫。而一些小型的框架或項目中,還是能夠見到 MySQLi 的身影。當然,小衆並不意味着不好,就像日常開發中,我們很少會在 PHP 環境中使用別的數據庫,那麼在自己的小項目中完全使用一套 MySQLi 來操作數據庫反而更加地方便快捷。同時,老項目如果要切換到 PHP7 版本的話,如果之前使用的是 MySQL(原始)連接的數據庫,也能夠快速地將 MySQL(原始)的代碼很方面地替換到 MySQLi 。
擴展的安裝及 MySQL8 需要注意的地方
MySQLi 的擴展是隨 PHP 源碼一起發佈的,我們在編譯 PHP 的時候加上 --with-mysqli 就可以了。現在默認的數據庫驅動都是使用的 mysqlnd ,libmysql 也已經基本淘汰了。所以在編譯時不需要再加上其它的參數,直接進行編譯即可。
在連接 MySQL8 的時候需要注意,因爲 MySQL8 服務器會默認使用 caching_sha2_password 作爲密碼的加密。而 PHP7.2.4 之前的版本中的 MySQLi 會使用 mysql_native_password 來對連接密碼進行加密,這樣就會導致無法連接上數據庫。大家可以修改 my.cnf 文件,設置 default_authentication_plugin=mysql_native_password ,讓 MySQL8 也使用 mysql_native_password 來加密用戶密碼。
面向過程式
上文說過,MySQLi 是支持兩種寫法的,也就是面向對象和麪向過程。簡單地理解就是一種是 MySQL(原始)擴展的寫法,另一種寫法是類似於 PDO 的寫法。我們先來看看面向過程的寫法。
$mysqli = mysqli_connect("localhost", "root", "", "blog_test");
$res = mysqli_query($mysqli, "SELECT * FROM zyblog_test_user");
$row = mysqli_fetch_assoc($res);
print_r($row);
是不是感覺 MySQL(原始)擴展的代碼要移植過來真的很方便。方法名上全部改成 mysqli_xxx 就可以了。
面向對象式
面向對象式的就有點像 PDO 。我們要先獲得一個連接句柄類,然後操作這個類就可以了。
$mysqli = new mysqli("localhost", "root", "", "blog_test");
$res = $mysqli->query("SELECT * FROM zyblog_test_user");
$row = $res->fetch_assoc();
print_r($row);
面向對象和麪向過程混用
另外,這兩種方式還可以混合使用,不過並不推薦。混合起來使用的話很容易讓看代碼的人暈頭轉向。所以,最好還是在一個項目中就堅持使用一種方式。
$mysqli = new mysqli("localhost", "root", "", "blog_test");
$res = mysqli_query($mysqli, "SELECT * FROM zyblog_test_user");
$row = $res->fetch_assoc();
print_r($row);
在這段代碼中,我們實例化了一個 mysqli 對象,然後使用面向過程的 mysqli_query() 函數來執行語句,接着又使用面向對象的方式來獲取結果集。是不是很亂?但是它是可以正常運行的。
總結
從上面的內容中可以看出,PDO 的特點是支持多種不同類型的數據庫,就像 Java 中的 JDBC 一樣。而 MySQLi 雖然只支持 MySQL 數據庫,但它卻可以同時支持面向對象和麪向過程兩種寫法。是我們針對老項目代碼進行升級優化的好幫手。同時,它還是現在入門 PHP 學習相關數據庫操作的首選。在接下來的文章中,我們將默認只使用 面向對象 式的寫法來繼續學習 MySQLi 擴展相關的知識。
測試代碼:
參考文檔:
https://www.php.net/manual/zh/mysqli.requirements.php
https://www.php.net/manual/zh/mysqli.installation.php
https://www.php.net/manual/zh/mysqli.overview.php
https://www.php.net/manual/zh/mysqli.quickstart.dual-interface.php
各自媒體平臺均可搜索【硬核項目經理】