php - PDO和PDOStatement為什麼會同時存在?這樣的設計是出於什麼考量呢?
我想大声告诉你
我想大声告诉你 2017-05-16 13:11:25
0
3
759

問題描述:
都知道自PHP 5.1.0 起,PDO就算是PHP的標配的一部分了,PDO提供了3個類PDOPDOStatement和不用說了,功能和定位啥的看名字都很清楚。 那麼問題來了:為什麼會同時存在PDO

PDOStatement這兩個類別? 為什麼會有這樣的疑問,先看下圖(圖截取自@PHP官網手冊):


圖片是PDO

PDOStatement

類所聲明的方法,可以看出,這兩個類別提供的方法雖然絕大部分不同,但是明顯核心方法有重疊或重複,例如:

PDO::query()
  • PDO::exec()

    都是執行一條SQL語句,只是回傳不同

    PDOStatement::execute()
  • 也是執行一條SQL語句,只是語句被預處理過
  • PDOStatement::execute()
  • 還好說,而
PDO::query()

PDO::exec() 同時存在的必要性又是什麼呢?而且還會造成使用和理解上面的不暢。 好吧,就算有同時存在的必要性那麼還是有一點為什麼要同時存在這兩個類別呢?

而不是一個類別(假如只有

PDO
類)就將這兩個類別所能做的事情一起做了呢? PDO 類別和
PDOStatement 類別之間是什麼關係呢? 如果 PDO 類用來執行SQL和管理鏈接,而

PDOStatement

類只用來處理結果集,那麼感覺就舒服順暢多了。 希望有大牛能給予解釋 PHP

PDO

這麼設計的考慮是什麼,真誠感謝~

我想大声告诉你
我想大声告诉你

全部回覆(3)
曾经蜡笔没有小新

我的理解是,一個用來執行普通的SQL,另一個可以進行參數綁定之類的…

仅有的幸福

我說一下個人理解,有錯誤的地方還請大家指正。
先來看看PDO類

PDO::prepare — Prepares a statement for execution and returns a statement object
PDO::query — Executes an SQL statement, returning a result set as a PDOStatement object

可以看到query()和prepare()都是回傳一個PDOStatement對象,那麼這就說明PDOStatement可以操作結果集。
再看PDO::prepare,手冊說是執行一條預處理語句,實際上他是得到一條預處理語句PDOStatement,然後再透過呼叫PDOStatement::execute() 來真正執行SQL。
通常我們一些專案都會使用prepare來執行SQL語句,這樣的做法是為了防止SQL注入,和提高相同模板SQL的查詢效能,引入官方手冊內容:
The query only needs to be parsed (or prepared) once, but can be executed multiple times with the same or different parameters. When the query is prepared, the database will analyze, compile and optimize its plan for qucuting the query. For com queries 和 ​​homimize its plans executing the query. For com queries sh ma plexs sh。 an application if there is a need to repeat the same query many times with different parameters. By using a prepared statement the application avoids repeating the analyze/compile/optimize cycle state asterohis ​​片面 fg. The ? query are being built up with unescaped input, SQL injection is still possible).

至於樓主說的PDO::query和PDO::exec不同,如下:

query是只執行一個select語句,exec是執行語句,insert, update,deletePDO::query執行一條SQL語句,如果通過,則傳回一個PDOStatement物件PDO::exec執行一條SQL語句,並傳回受影響的行數。此函數不會傳回結果集合。
PDOStatement::execute前面也說了一些介紹,他是PDOStatement下的一個子函數,一個特性在於它支援綁定參數,不用考慮SQL注入安全性問題,另一個特性是支援多次執行,同模板SQL有助於性能提高。
如果你只查詢一個語句,用query好處是query回傳的結果集可以直接遍歷。
而你用exec執行他是只回傳受影響的行數,並不是PDOStatement結果集,你是沒辦法直接遍歷的。按照官方建議使用query或execute。
我理解的大概就是這樣。

Ty80
1.exec
2.query
3.prepare+execute

上面3種方法都可以執行SQL,如果覺得容易混淆,可以只用第3種方法.
因為只要是exec和query能實現的,prepare+execute也一樣能實現.
而prepare+execute能實現的,例如預處理參數化查詢,exec和query卻不能實現.
exec和query更多是為了方便而出現的,比如有時候我們執行的SQL語句並沒有外來的參數,這時用exec和query就會簡潔些,顯然exec更適合執行單條寫操作(INSERT/UPDATE/DELETE)語句,因為exec能直接返回受影響的行,如果你用query,你還得調用rowCount()才能獲得受影響的行,比如:
$db->query($sql)->rowCount();$db->query($sql)->rowCount();
当如果你执行没有外来参数的SQL获取SELECT结果,这时则应该用query而不是exec:
$db->query($sql)->fetchAll();當如果你執行沒有外來參數的SQL取得SELECT結果,這時則應該用query而不是exec:
$db->query($sql)->fetchAll();

如果你執行的SQL帶有輸入的參數,為了防止SQL注入,你應該用prepare:🎜
$sql = "SELECT * FROM `io_post` WHERE `id` IN (?, ?, ?)";
$params = array(1, 3, 5); //$params是一个参数数组,元素按顺序一一对应$sql中的问号?占位符
$stmt = $db->prepare($sql);
$stmt->execute($params); //execute会自动对参数数组的每个元素进行bindValue
$stmt->fetchAll(); //如SELECT结果集
$stmt->rowCount(); //如INSERT/UPDATE/DELETE受影响的行
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板