首頁 > 後端開發 > php教程 > PHP之詳解PDO

PHP之詳解PDO

*文
發布: 2023-03-18 15:06:02
原創
21770 人瀏覽過

本文主要介紹了詳解PHP中的PDO類,PDO類可以幫助人們更方便地在PHP中使用資料庫。希望對大家使用PDO有幫助。

 簡介

咱一起來看看PDO類別。 PDO是PHP Data Objects的縮寫,它被描述為「在PHP中存取資料庫的輕量級,相容性的介面」。儘管它的名字不好聽,但PDO是一個在PHP中存取資料庫會讓人喜愛的方式。
與MySQLi的不同

MySQLi和PDO很相似,都有兩個面向主要差異:

1.MySQLi只能存取MySQL,但PDO可以存取12種不同的資料庫

2.PDO沒有普通函數呼叫(mysqli_*functions)
開始步驟

#首先,你得確定一下你的PHP是否安裝了PDO外掛。你可以用$test=new PDO()的結果來測試。如果提示說是參數不匹配,那證明已經安裝了PDO插件,如果說是物件不存在,你得先確認一下在pho.ini中php_pdo_yourssqlserverhere.extis是否被註解掉了。如果沒有這句話,那你得安裝PDO了,這裡就不囉嗦了。

連接

現在我們確認伺服器已經運作,開始連接資料庫:
 

$dsn = 'mysql:dbname=demo;host=localhost;port=3306';
$username = 'root';
$password = 'password_here';
try {
 $db = new PDO($dsn, $username, $password); // also allows an extra parameter of configuration
} catch(PDOException $e) {
 die(&#39;Could not connect to the database:<br/>&#39; . $e);
}
登入後複製

除$dsn之外,所有語句和變數都能自我解釋。 DSN指的是資料來源名稱,有多種輸入類型。最常見的一種是我們剛剛使用的這種,PHP官網解釋了 其他可用的DSN 。

你可以省去DSN的其他額外參數,只需要在資料庫驅動後面帶個冒號,例如(mysql:)。在這種情況下PDO將會嘗試連線到本機資料庫。就像當你使用MySQLi時需要在查詢中指定資料庫名稱一樣。

最後一件你需要注意的事情就是我們用try-catch區塊包裹了我們的初始化物件。 PDO連線失敗的時候將會拋出PDOException異常而不是查詢失敗的時候。如果你願意你可以使用下面程式​​碼$db=line來選擇異常的模式。
 

$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
登入後複製

或你可以直接在PDO初始化時傳遞參數:
 

#
$db = new PDO($dsn, $username, $password, array (
 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
));
登入後複製

我們現在使用的是錯誤的方式-在失敗時候簡單回傳false,我們是沒有理由不對例外進行處理的。

基本查詢

在PDO中使用query和exec兩種方法使得對資料庫查詢變得非常簡單。如果你想要得到查詢結果的行數exec是非常好用的,因此對SELECT查詢語句是非常有用的。

現在我們透過下面的一個例子來查看這兩個方法:
 

#
$statement = <<<SQL
 SELECT *
 FROM `foods`
 WHERE `healthy` = 0
SQL;
 
$foods = $db->query($statement);
登入後複製

##假設我們的查詢是正確的,$foods現在是一個PDO Statement對象,我們可以用它獲取到我們的結果或是查看這次查詢中一共查到多少條結果集。


行數

不足的是,PDO並沒有提供一個統一的方法去計算回傳的行數。 PDO Statement包含了一個叫做rowCount的方法,但這個方法不能保證在每個SQL驅動程式中運作(幸運的是,它能夠在Mysql資料庫中運作)。

如果你的SQL驅動程式不支援這個方法,你也有2個選擇:使用二次查詢(SELECT COUNT(*))或使用簡單的count($foods)得到行數。

幸運的是對我們的MySQL例子,我們可以使用下面的簡單方法來輸出正確的行數。

 

echo $foods->rowCount();
登入後複製

#遍歷結果集

列印出這些可口的食物一點也不困難:

 

foreach($foods->FetchAll() as $food) {
 echo $food[&#39;name&#39;] . &#39;<br />&#39;;
}
登入後複製

#唯一要注意的是PDO也支援Fetch方法,而這個方法只會傳回第一個結果,這對只需要查詢一條結果集是非常有用的。


轉義用戶輸入(的特殊字元)

你可曾聽過(mysqli_)real_escape_string,這是用來確保使用者輸入安全資料。 PDO提供了一個方法叫做quote,這個方法可以把輸入字串中帶有引號的地方進行特殊字元轉義。

 

$input: this is&#39;s&#39; a &#39;&#39;&#39;pretty dange&#39;rous str&#39;ing
登入後複製

在轉義後,最終得到下面結果:

 

$db->quote($input): &#39;this is\&#39;s\&#39; a \&#39;\&#39;\&#39;pretty dange\&#39;rous str\&#39;ing&#39;
exec()
登入後複製

如同上述的,你可以使用exec()方法實作UPDATE,DELETE和INSERT 操作,執行後它會傳回受影響行數的數量:

 

$statement = <<<SQL
 DELETE FROM `foods`
 WHERE `healthy` = 1;
SQL;
 
echo $db->exec($statement); // outputs number of deleted rows
登入後複製

預處理語句

儘管exec方法和查詢在PHP中仍然被大量使用和支持,但是PHP官網上還是要求大家用預處理語句的方式來替代。為什麼呢?主要是因為:它比較安全。預處理語句不會直接在實際查詢中插入參數,這避免了許多潛在的SQL注入。

然而出於某種原因,PDO實際上並沒有真正的使用預處理,它是在模擬預處理方式,在將語句傳給SQL伺服器之前會把參數資料插入到語句中,這使得某些系統容易受到SQL注入。

如果你的SQL服务器不真正的支持预处理,我们可以很容易的通过如下方式在PDO初始化时传参来修复这个问题:

$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
登入後複製

接下来开始我们的第一个预处理语句吧:

$statement = $db->prepare(&#39;SELECT * FROM foods WHERE `name`=? AND `healthy`=?&#39;);
$statement2 = $db->prepare(&#39;SELECT * FROM foods WHERE `name`=:name AND `healthy`=:healthy)&#39;;
登入後複製

正如你所见,有两种创建参数的方法,命名的与匿名的(不可以同时出现在一个语句中)。然后你可以使用bindValue来敲进你的输入:

$statement->bindValue(1, &#39;Cake&#39;);
$statement->bindValue(2, true);
 
$statement2->bindValue(&#39;:name&#39;, &#39;Pie&#39;);
$statement2->bindValue(&#39;:healthy&#39;, false);
登入後複製

注意使用命名参数的时候你要包含进冒号(:)。PDO还有一个bindParam方法,可以通过引用绑定数值,也就是说它只在语句执行的时候查找相应数值。

现在剩下的唯一要做的事情,就是执行我们的语句:

$statement->execute();
$statement2->execute();
 
// Get our results:
$cake = $statement->Fetch();
$pie = $statement2->Fetch();
登入後複製

为了避免只使用bindValue带来的代码碎片,你可以用数组给execute方法作为参数,像这样:

$statement->execute(array(1 => &#39;Cake&#39;, 2 => true));
$statement2->execute(array(&#39;:name&#39; => &#39;Pie&#39;, &#39;:healthy&#39; => false));
登入後複製

事务

前面我们已经描述过了什么是事务:

一个事务就是执行一组查询,但是并不保存他们的影响到数据库中。这样做的好处是如果你执行了4条相互依赖的插入语句,当有一条失败后,你可以回滚使得其他的数据不能够插入到数据库中,确保相互依赖的字段能够正确的插入。你需要确保你使用的数据库引擎支持事务。
开启事务

你可以很简单的使用beginTransaction()方法开启一个事务:

$db->beginTransaction();
 
$db->inTransaction(); // true!
登入後複製

然后你可以继续执行你的数据库操作语句,在最后提交事务:

$db->commit();
登入後複製

还有类似MySQLi中的rollBack()方法,但是它并不是回滚所有的类型(例如在MySQL中使用DROP TABLE),这个方法并不是真正的可靠,我建议尽量避免依赖此方法。

其他有用的选项

有几个选项你可以考虑用一下。这些可以作为你的对象初始化时候的第四个参数输入。

 $options = array($option1 => $value1, $option[..]);
$db = new PDO($dsn, $username, $password, $options);
登入後複製

PDO::ATTR_DEFAULT_FETCH_MODE

你可以选择PDO将返回的是什么类型的结果集,如PDO::FETCH_ASSOC,会允许你使用$result['column_name'],或者PDO::FETCH_OBJ,会返回一个匿名对象,以便你使用$result->column_name

你还可以将结果放入一个特定的类(模型),可以通过给每一个单独的查询设置一个读取模式,就像这样:

$query = $db->query(&#39;SELECT * FROM `foods`&#39;);
$foods = $query->fetchAll(PDO::FETCH_CLASS, &#39;Food&#39;);
登入後複製

- 所有读取模式

上面我们已经解释过这一条了,但喜欢TryCatch的人需要用到:PDO::ERRMODE_EXCEPTION。如果不论什么原因你想抛出PHP警告,就使用PDO::ERRMODE_WARNING。

PDO::ATTR_TIMEOUT

当你为载入时间而着急时,你可以使用此属性来为你的查询指定一个超时时间,单位是秒. 注意,如果超过你设置的时间,缺省会抛出E_WARNING异常, 除非 PDO::ATTR_ERRMODE 被改变.

更多属性信息可以在 PHP官网的属性设置 里查看到.
最后的思考

PDO是一个在PHP中访问你的数据库的很棒的方式,可以认为是最好的方式。除非你拒绝使用面向对象的方法或是太习惯 MySQLi 的方法名称,否则没有理由不使用PDO。

更好的是完全切换到只使用预处理语句,这最终将使你的生活更轻松!

相关推荐:

php如何利用PDO访问oracle数据库的方法详解

PHP中关于PDO数据访问抽象层的功能操作的介绍

使用PDO操作MySQL数据库的实例分享(收藏)

以上是PHP之詳解PDO的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板