在 PDO 的學習過程當中,咱們常常會在使用事務的時候加上 try...catch 來進行事務的回滾操做,可是你們有沒有注意到默認狀況下 PDO 是如何處理錯誤語句致使的數據庫操做失敗問題呢?今天,咱們就來學習一下。php
PDO 提供了三種不一樣的錯誤處理方式:mysql
PDO::ERRMODE_SILENT,這是 PDO 默認的處理方式,只是簡單地設置錯誤碼,能夠使用 PDO::errorCode() 和 PDO::errorInfo() 方法來檢查語句和數據庫對象git
PDO::ERRMODE_WARNING,除設置錯誤碼以外,PDO 還將發出一條傳統的 E_WARNING 信息。若是隻是想看看發生了什麼問題且不中斷應用程序的流程,那麼此設置在調試/測試期間很是有用。github
PDO::ERRMODE_EXCEPTION,除設置錯誤碼以外,PDO 還將拋出一個 PDOException 異常類並設置它的屬性來反射錯誤碼和錯誤信息。面試
原來默認狀況下,咱們的 PDO 是不會處理錯誤信息的,這個你知道嗎?若是不信的話,咱們繼續向下看具體的測試狀況。不過,首先咱們要說明的是,PDO 的錯誤處理機制針對的是 PDO 對象中的數據操做能力,若是在實例化 PDO 對象的時候就產生了錯誤,好比數據庫鏈接信息不對,那麼直接就會拋出異常。( PHP5 中會直接返回一個 NULL,PHP7會拋出異常! )sql
$pdo = new PDO('mysql:host=127.0.0.1;port=3306;dbname=blog_test1', 'root', ''); // Fatal error: Uncaught PDOException: SQLSTATE[HY000] [1049] Unknown database 'blog_test1'
blog_test1 表並不存在,因此在 new PDO 的時候就已經直接會拋出異常了。這個在實例化鏈接數據庫過程當中的錯誤處理機制是固定的,不是咱們能修改的錯誤處理機制,畢竟若是連數據庫鏈接都沒法創建的話,就不用談後面的任何操做了。數據庫
$pdo = new PDO('mysql:host=127.0.0.1;port=3306;dbname=blog_test', 'root', ''); $pdo->query('select * from aabbcc'); var_dump($pdo->errorCode()); // string(5) "42S02" var_dump($pdo->errorInfo()); // array(3) { // [0]=> // string(5) "42S02" // [1]=> // int(1146) // [2]=> // string(38) "Table 'blog_test.aabbcc' doesn't exist" // }
在上面的測試代碼中,咱們查詢了 aabbcc 這個表,但其實數據庫中並不存在這個表。若是不使用 errorCode() 或者 errorInfo() 的話,這段代碼不會有任何輸出,也就是說,不會有任何錯誤信息讓你看到,代碼就直接運行過去了。框架
這個就是 PDO 在默認狀況下的錯誤處理機制。其實,這樣的處理並很差,由於若是咱們忘記設置錯誤處理機制的話,就會致使一些錯誤沒法呈現,並且並很差調試。ide
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); $pdo->query('select * from aabbcc'); // Warning: PDO::query(): SQLSTATE[42S02]: Base table or view not found: 1146 Table 'blog_test.aabbcc' doesn't exist
在設置錯誤處理機制爲警告後,PDO 會拋出一個不影響程序執行的 warning 信息。可是,若是咱們修改了 ini 文件中錯誤處理機制後,也多是看不到警告信息的。不過相對於默認處理的狀況來講,有一條警告信息已經很是好了。學習
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->query('select * from aabbcc'); // Fatal error: Uncaught PDOException: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'blog_test.aabbcc' doesn't exist
最後,咱們將錯誤處理機制設置爲拋出異常。總算是能讓程序停止運行而且報出 Fatal error 錯誤了,同時,這個異常信息也是能夠經過 try...catch 來捕獲到的。這樣的開發纔是咱們最須要的開發形式。
在上述測試代碼中,咱們使用的是 setAttribute() 方法來設置 PDO 的錯誤處理屬性,但其實咱們能夠在實例化 PDO 類時就指定一些須要的屬性。
$pdo = new PDO('mysql:host=127.0.0.1;port=3306;dbname=blog_test', 'root', '', [PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING]); $pdo->query('select * from aabbcc'); // Warning: PDO::query(): SQLSTATE[42S02]: Base table or view not found: 1146 Table 'blog_test.aabbcc' doesn't exist
PDO 已是如今的主流數據庫鏈接擴展,也是各類框架的必備連庫擴展,可是若是不深刻的學習的話,不少人可能還真不知道不少關於 PDO 的一些知識。框架在爲咱們帶來便利的同時,也讓咱們變得更「笨」,因此,學習仍是要更多地接觸底層地知識,省得在面試的時候須要手寫代碼的時候手足無措。
測試代碼:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202008/source/%E5%AD%A6%E4%B9%A0PDO%E4%B8%AD%E7%9A%84%E9%94%99%E8%AF%AF%E4%B8%8E%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86%E6%A8%A1%E5%BC%8F.php
參考文檔:
https://www.php.net/manual/zh/pdo.error-handling.php
===============
關注公衆號:【硬核項目經理】