国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

(唯一合適) PDO 教程

sf190404 / 1612人閱讀

摘要:是什么首先思考為什么選擇是一個數據訪問抽象層抽象是雙重的一個是眾所周知但不太重要的另一個是模糊的但是是最重要的眾所周知為不同的數據庫提供了統一的接口雖然這個功能本身很龐大但是對于固定程序來說不是過于重要的事情基本所有的程序都是使用統一的后端

PDO是什么

首先思考, 為什么選擇PDO

PDO 是一個數據訪問抽象層(Database Access Abstraction Layer). 抽象是雙重的: 一個是眾所周知但不太重要的. 另一個是模糊的但是是最重要的.
眾所周知 PDO 為不同的數據庫提供了統一的接口. 雖然這個功能本身很龐大, 但是對于固定程序來說不是過于重要的事情, 基本所有的程序都是使用統一的后端數據庫. 盡管有一些謠言, 但是通過改變單行 PDO 配置來切換后端數據庫是不可能的-由于不同的 SQL 風格(為此, 需要使用像 DQL 這樣的平均查詢語言). 因此對于普通的 LAMP 開發者來說, 這一點是微不足道的, 并且對他而言, PDO只是熟悉的 mysql(i)_query() 函數的另一個更復雜版本. 但實際上它不是, 它有豐富的其他功能.
PDO 不僅抽象了數據庫API, 還抽象了基本操作, 否則必須在每個應用程序中重復數百次, 使您的代碼非常WET. 不同于 mysqlmysqli , 兩個都不能直接使用低級裸 APIs(但僅作為某些更高級別抽象層的構建材料), PDO就是這樣的抽象. 雖然仍是不完整的, 但是至少可用.
真正的PDO好處是:

安全性 (可用的準備語句)

可用性 (許多輔助函數可以自動執行日常操作)

可重用性 (用于訪問大量數據庫的統一API, 從SQLITE到oracle)

請注意, 盡管 PDO 是原生數據庫驅動程序中最好的, 但對于現代WEB應用程序來說, 請考慮將使用有查詢構建器的 ORM 或者與其他更高抽象級別的庫一起使用, 只是偶爾使用原生的PDO. 好的ORM比如 Doctrine, Eloquent, RedBeanYii::AR. Aura.SQL 是具有很多附加功能的使用PDO包裝器的一個很好的例子.
無論哪種方式, 首先要了解基本工具是件好事. 那么, 讓我們開始吧:

connection DSN

PDO有一個叫 DSN 的預想接方式. 它并不復雜-PDO需要你在三個不同的位置輸入不同的配置, 而不是一個簡單的選項列表.

database driver, host, db(schema) namecharset, 以及不常使用的 portunix_socket 設置 DSN

user_namepassword 設置構造方法

其他所有的配置在options數組

其中 DSN 是以分號分隔的字符串, 由 param=value 鍵值對組成, 從驅動程序名稱和冒號開始:

    mysql:host=localhost;dbname=test;port=3306;charset=utf8mb4
driver^  ^colon           ^param=value pair   ^semicolon

注意, 遵循正確的格式是非常重要的- DSN中不能使用 空格, 引號, 和其他的符號, 只能使用參數, 值和定界符. 就像手冊上展示的.

這里有一個例子:

$host = "127.0.0.1";
$db = "test";
$pass = "root";
$charset = "utf8mb4";

$dsn = "mysql:host={$host};dbnamej={$db};charset={$charset}";
$options = [
    PDO::ATR_ERRMODE => PDO::ERRMODE_EXECPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES => false,
];
try {
    $pdo = new PDO($dsn, $user, $pass, $options);
} catch (PDOException $e) {
}

設置了所有上述變量屬性, 我們將在 $pdo 變量中得到一個正確的 PDO 實例.
使用舊mysql擴展用戶重要通知

不同于 mysql_* 函數, 可以在代碼的任意位置使用, pdo 實例被存儲在一個變量中, 那就意味著只能在函數內部進行訪問. 因此, 必須通過函數參數傳遞或使用更高級的技術, 比如IOC容器.

連接只用創建一次. 不要在函數, 類構造函數創建連接, 否則, 會創建多個連接, 最終導致數據庫服務宕機. 因此必須創建唯一的 PDO 實例, 讓整個腳本使用.(適用于FPM模式)

通過DSN設置字符集是非常重要的-這是唯一正確的方式因為它會告訴PDO哪個字符集會被使用. 因此, 忘記通過 Query 運行SET NAMES 或者通過 PDO::MYSQL_ATTR_INIT_COMMAND. 只有當PHP版本過低時(低于5.3.6), 才可以使用 SET NAMES 查詢, 并且關閉仿真模式.

更多關于連接的內容可以在 連接MySQL查看

運行查詢 PDO::query()

使用 PDO 有兩種方式運行查詢. 如果查詢中沒有使用變量, 可以使用 PDO::query 方法. 它會運行查詢并返回一個 PDOStatement 類的對象, 該類與 mysql_query 返回的資源大致相同, 特別時從中獲取實際記錄的操作:

$stmt = $pdo->query("SELECT name FROM users");
while ($row = $stmt->fetch()) {
    echo $row["name"] . "
";
}

并且 query() 方法允許我們使用一個整潔的方法連接 SELECT 查詢, 如下所示.

預處理, 防止SQL注入

放棄熟悉的 mysql_query()函數 并進入嚴格數據對象領域的主要原因是 PDO 已經準備好了開箱即用的預處理語句. 如果要在語句中使用變量, 預處理語句是唯一正確運行的方式. 它如此重要的原因在 The Hitchhiker"s Guide to SQL Injection prevention.有詳細的解釋.
對于運行的查詢, 如果至少使用一個變量, 你必須使用占位符替換它. 準備執行語句, 然后分別傳入變量執行.
長話短說, 它不像感覺的那么困難. 在大多數例子中, 你只需要使用函數 prepareexecute .
首先, 需要修改查詢, 在使用變量的位置添加占位符, 就像這樣

$sql = "SELECT * FROM users WHERE email = "{$email}" AND status = "{$status}"";

改為

$sql = "SELECT * FROM users where email = ? and status = ?";

或者

$sql = "SELECT * FROM users where email = :email AND status = :status";

注意 PDO 支持位置(?)和命名(:email)占位符, 后者始終以冒號開始,并且只能使用字母, 數字和下劃線. 還需要注意 占位符周圍不能使用引號 .
一個查詢使用了占位符, 就必須使用PDO::prepare()方法預處理. 這個方法返回一個和我們上邊討論的相同的 PDOStatement 對象, 但是沒有綁定任何數據.
最后, 必須使用 PDOStatement 對象的 execute() 方法執行查詢, 并且通過數組形式傳遞參數. 之后, 就可以從語句中得到結果數據(如果適用).

$stmt = $pdo->prepare("SELECT * FROM users WHERES email = ? AND status = ?");
$stmt->execute([$email, $status])
$user = $stmt->fetch();

// or
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email AND status = :status");
$stmt->execute(["email" => $email, "status" => $status]);
$user = $stmt->fetch();

可以看到, 位置占位符, 你需要提供一個索引數組. 命名占位符, 需要提供一個關聯數組, 并且鍵要匹配查詢中的占位符. 同一個查詢中不能混合位置占位符和命名占位符.
位置占位符可以讓你寫更簡短的代碼, 但是對參數順序是敏感的(必須于查詢中參數的順序一致). 雖然命名占位符使代碼更冗長, 但是允許隨機參數綁定.
另外需要注意, 雖然存在普遍的誤解, 但是數組鍵中 : 不是必須的.
執行后就可以使用支持的方法獲取結果.

更多的例子可以查看(respective article)[https://phpdelusions.net/pdo_...].

參數綁定

將數據傳入 execute() (如上所示)方法中應被視為默認的最方便的方式. 如果使用這個方法, 所有參數都將會綁定為字符串(如果使用NULL值, 將會使用SQL NULL發送給查詢), 大多數時候都沒有問題.
但是, 有時候最好明確設置類型. 可能情況如下:

開啟仿真模式的 LIMIT 子句(或者其他不能接受字符串操作數的 SQL 子句)

可能受到錯誤操作數類型影響具有特殊查詢計劃的復雜特殊查詢

特有的列類型, 像 bigint boolean 必須綁定精確的操作數(為了將 BIGINT 綁定為 PDO::PARAM_INT 需要基于 mysqlnd)

這種情況下, 必須使用顯式綁定, 可以從 bindvalue()bindParam() 兩個函數中選擇一個. 前者是推薦使用的, 它不像 bindParam()具有一定的副作用.

查詢可以綁定的部分

了解哪些查詢部分可以使用參數綁定哪些部分不能使用是非常重要的. 事實上, 這個列表是非常短的: 只有字符串和數字字面量可以被綁定. 只要你的數據在查詢中能被表示為數字或者帶引號的字符串, 就可以被綁定. 其他所有情況你不能使用 PDO 預處理語句: 既不是標識符也不是逗號分隔列表, 或者是引用的文字字符串的一部分, 或者其他任意查詢部分都不能使用預準備語句綁定
最常見的用例解決方案可以在[本章的響應部分查看]()

預處理, 多次執行

有時候你可以使用預處理多次執行準備好的查詢, 比一次又一次執行相同的查詢快一點, 因為它只解析查詢一次. 如果可以執行另一個PHP實例中的預處理語句, 這個功能就是非常有用的, 但是事實并非如此. 只會在同一個實例中重復相同的查詢, 這在常規的PHP腳本中很少使用到, 并限制了此功能用于重復插入和更新.

$data = [
    1 => 1000,
    2 => 200,
    3 => 200,
];
$stmt = $pdo->prepare("UPDATE users SET bonus = bonus + ? where id = ?");
foreach ($data as $id => $bonus) {
    $stmt->execute([$bonus, $id]);
}

注意這個功能有點被高估了. 不僅需要討論, 而且性能提升也不是很大 - 查詢解析有時候是
很快的. 而且只有在關閉仿真模式的時候才能帶來性能提升.

運行SELECT INSERT UPDATE DELETE語句

這些查詢沒有什么特別之處, 對PDO來說他們都是一樣的. 運行哪個查詢并不重要.
如上所示, 需要準備帶有占位符的預處理查詢, 傳入變量并執行. DELETESELECT 的處理過程是基本相同的. 僅有的不同點是( DML查詢不會返回任何數據), 你可以使用鏈式方法, 調用 execute()prepare().

$sql = "UPDATE users SET name = ? where id = ?";
$pdo->prepare($sql)->execute([$name, $id]);

然而, 你像獲得影響行數, 代碼將和無聊的三行代碼相同:

$stmt = $pdo->prepare("DELETE FROM goods where category = ?");
$stmt->execute([$cat]);
$deleted = $stmt->rowCount();

更多的例子可以在respective article.找到.

從statement獲取數據 foreach

我們已經見過這個函數了, 現在讓我們仔細看看. 它從數據庫獲取單行數據, 在結果集中移動內部指針, 因此, 對函數的后續調用將逐個返回所有行. 這個方法和 mysql_fetch_array() 大致相同但在工作模式稍微有點不同: 代替很多不同函數( mysql_fetch_assoc() mysql_fetch_row), 這個只有一個方法, 但是它的行為可以通過一個參數改變. 在 PDO 中有很多的獲取模式, 稍后我們詳細討論, 這里有一些簡單的實例:

PDO::FETCH_NUM 返回索引數組

PDO::FETCH_ASSOC 返回關聯數組

PDO::FETCH_BOTH 以上兩者都包含

PDO::FETCH_OBJ 返回對象

PDO::FETCH_LAZY 允許三個(索引數組, 關聯數組, 對象)方法沒有內存開銷.

從上面可以看出, 這個必須在兩種情況下使用:

當只需要一行時, 只獲取一行

    $row = $stmt->fetch(PDO::FETCH_ASSOC);

將以關聯數組的方式從語句中獲取一行

當我們需要在使用之前處理返回數據. 在這種情況下, 必須通過while循環運行, 如上所示.

另一種有用的模式是 PDO::FETCH_CLASS 可以創建一個特定類的對象

$news = $pdo->query("select * from news")->fetchAll(PDO::FETCH_CLASS, "News");

將生成一個News類對象的數組, 并且通過返回值設置類屬性. 注意這個模式下:

屬性會在構造方法之前設置

所有未定義的屬性都會調用 __set魔術方法

如果沒有 __set方法, 將會創建新屬性

私有屬性也會被設置, 這有點意外但是非常方便

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/31055.html

相關文章

  • 我感覺這是史上最牛的防sql注入方法類

    摘要:早在年我就開始寫這個類庫了,平時在工作中,將一些好的想法,一些問題的解決方法等融合進來,歷時兩年多,經過不斷的實踐,我感覺它已經很成熟了,于是它來到了你面前我的倉庫地址這里假設有一個數據表,其中為主鍵。 早在2015年我就開始寫這個PHP類庫了,平時在工作中,將一些好的想法,一些問題的解決方法等融合進來,歷時兩年多,經過不斷的實踐,我感覺它已經很成熟了,于是它來到了你面前! 我的倉庫地...

    dockerclub 評論0 收藏0
  • 使用SAE和Gitcafe開發網站應用

    摘要:原文使用和開發網站應用在領域目前看來新浪云走的比較早,也比較成熟。新浪云需要使用新浪微博的帳號才能登錄和使用。目前,新浪云需要進行實名認證才能創建個以上的應用,所以推薦進行實名認證。 原文:使用SAE和Gitcafe開發網站應用 在PaaS領域目前看來新浪云走的比較早,也比較成熟。相比IaaS,PaaS更能為企業或個人帶來成本上的節約。本文以php為例,記錄了如何在新浪云上注冊創建自...

    liuhh 評論0 收藏0
  • PHP-X 系列教程:內置函數的使用

    摘要:本文主要介紹內置函數的使用,在擴展開發中,會經常用到這些內置函數,的封裝,使得調用這些函數像代碼一樣簡單。的使用方法與語言的是完全一致的。包括的超全局變量和其他代碼使用關鍵詞聲明的全局變量。 本文主要介紹PHP-X內置函數的使用,在PHP擴展開發中,會經常用到這些內置函數,PHP-X的封裝,使得調用這些函數像PHP代碼一樣簡單。 echo 在擴展中需要輸出一些內容,可以使用echo函數...

    _Zhao 評論0 收藏0
  • yii過濾xss代碼,防止sql注入教程

    摘要:好啦,我們看看在框架的不同版本中是怎么處理攻擊,注入等問題的。那要是,又是怎樣處理的喃考慮目前國內網站大部分采集文章十分頻繁,更有甚者不注明原文出處,原作者更希望看客們查看原文,以防有任何問題不能更新所有文章,避免誤導繼續閱讀 作者:白狼 出處:http://www.manks.top/yii2_filter_xss_code_or_safe_to_database.html 本文版權...

    Shonim 評論0 收藏0
  • 寫一個“特殊”的查詢構造器 - (前言)

    摘要:而在項目開發中,我們想要的是一個更好用的可維護的工具,此時,對代碼的封裝模塊化就顯得尤為重要,于是出現了兩種方案查詢構造器,對象關系映射。典型環境下按照一般的查詢構造器處理就行。 文章目錄 寫一個特殊的查詢構造器 - (前言) 寫一個特殊的查詢構造器 - (一、程序結構,基礎封裝) 寫一個特殊的查詢構造器 - (二、第一條語句) 寫一個特殊的查詢構造器 - (三、條件查詢) 寫一個特殊...

    GitChat 評論0 收藏0

發表評論

0條評論

sf190404

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<