PHP最佳實踐之資料庫

xx19941215發表於2019-02-16
PDO擴充套件

PHP原生提供了PDO擴充套件,意思是PHP資料物件。

資料庫連結和DSN

DSN是指資料來源名稱,提供資料庫連結的詳細資訊。一般包含以下資訊:

  • 主機名或者IP地址

  • 埠號

  • 資料庫名

  • 字符集

以上資訊構成的DSN可以用於PDO類建構函式的第一個引數,第二個和第三個引數分別是資料庫的使用者名稱和密碼。如果資料庫需要認證,則需要提供這兩個 引數。

<?php
try {
    $pdo = new PDO(
        `mysql:host = 127.0.0.1;dbname=books;port=3306;charset=utf8`,
        `USERNAME`,
        `PASSWORD`
    );
} catch(PDOException $e) {
    echo "Database connection failed";
    exit;
}
保證密碼憑證的安全

把資料庫憑證儲存在一個位於文件根目錄之外的配置檔案中,然後在需要的檔案中匯入這個檔案。

預處理語句

在SQL中使用使用者的輸入時,一定要過濾。因此需要使用PDO擴充套件的預處理語句和引數繫結,這項操作非常簡單。預處理語句是PDO物件的例項,不過我們很少直接去例項化這個類,而是通過PDO例項的prepare方法獲得預處理語句的物件。這個方法得第一個引數是一個sql語句字串,返回值是一個PDOStatement例項:

<?php
$sql = `SELECT id FROM users WHERE email = :email`;
$statement = $pdo->prepare($sql);

在這個SQL語句中,email這個值可以安全的繫結任何值。

<?php
$sql = `SELECT id FROM users WHERE email = :email`;
$statement = $pdo->prepare($sql);
$email =  filter_input(INPUT_GET, `email`);
$statement->bindValue(`:email`, $email);

預處理語句會自動過濾$email的值。PDOStatement的第三個引數可以制定繫結值的型別,不填的話預設就是字串型別。可選的常量型別如下

  • PDO::PARAM_BOOL

  • PDO::PARAM_NULL

  • PDO::PARAM_INT

  • PDO::PARAM_STR(預設值)

查詢結果

如果執行的是select方法,返回的資料我們需要使用fetch()、fetchAll()、fetchColumn()和fetchObject()方法獲取查詢結果。

//把預處理語句獲得的結果當成關聯陣列處理
$sql = `SELECT id, email FROM users WHERE email = :email`;
$statement = $pdo->prepare($sql);
$email = filter_input(INPUT_GET, `email`);
$statement->bindValue(`:email`, $email);
$statement->execute();
//迭代結果
while(($result = $statement->fetch(PDO::FETCH_ASSOC)) !== false) {
    echo $result[`email`];
}

fetch、fetchAll方法的引數可選

  • PDO::FETCH_ASSOC:返回一個關聯陣列

  • PDO::FETCH_NUM:返回一個鍵為數字的陣列,陣列的鍵是資料庫列在查詢結果中的索引

  • PDO::FETCH_BOTH:返回一個既有鍵為列名又有鍵為數字的陣列。

  • PDO::FETCH_OBJ:讓fetch()和fetchAll()返回一個物件,物件的屬性是資料庫的列名。
    不推薦使用fetchAll(),除非你可以十分確定可用記憶體放得下整個查詢結果。如果只關心查詢結果中的一列,可以使用fetchColumn()方法,這個方法的作用和fetch()方法類似,返回查詢結果中下一行的某一列,該方法只有一個引數用於制定所需要的索引。

// 構建並執行SQL查詢
$sql = `SELECT id, name FROM users WHERE email = :email`;
$statement = $pdo->prepare($sql);
$email = filter_input(INPUT_GET, `email`);
$statement->bindValue(`:email`,  $email);
$statement->execute();

while(($emal = $statament->fetchCoulmn(1)) !== false) {
    echo $email;
}

因為在SQL語句中,email出現在了第二個欄位的位置,所以這裡使用索引1取出來。我們還可以使用fetchObj()方法來獲取查詢結果中的行,這個方法把行行當成物件,物件的屬性是查詢結果中的列。

// 構建並執行SQL查詢
$sql = `SELECT id, name FROM users WHERE email = :email`;
$statement = $pdo->prepare($sql);
$email = filter_input(INPUT_GET, `email`);
$statement->bindValue(`:email`,  $email);
$statement->execute();

while(($result = $statament->fetchObj()) !== false) {
    echo $result->email;
}
事務

事務是指把一系列資料庫語句當成單個的邏輯執行單元執行,也就是說事務中的一系列SQL查詢要麼都成功,要麼不執行。事務的原子效能保證資料的一致性、安全性和永續性。事務還有一個很好的副作用就是提升效能,因為事務是把多個查詢排成佇列,一次性全部執行。

專題系列

PHP專題系列目錄地址:https://github.com/xx19941215/webBlog
PHP專題系列預計寫二十篇左右,主要總結我們日常PHP開發中容易忽略的基礎知識和現代PHP開發中關於規範、部署、優化的一些實戰性建議,同時還有對Javascript語言特點的深入研究。

相關文章