鍍金池/ 教程/ PHP/ PHP 與 MySQL
驗證郵件地址
自動加載類
PHP 與 MySQL
緩存 PHP opcode
檢測一個值是否為 null 或 false
PHP 標(biāo)簽
從性能角度來看單引號和雙引號
發(fā)送郵件
處理日期和時間
define() vs. const
配置 Web 服務(wù)器提供 PHP 服務(wù)
PHP 與 UTF-8
我們在使用哪個版本的 PHP?
凈化 HTML 輸入和輸出
PHP 與正則表達式
存儲密碼
PHP 與 Memcached

PHP 與 MySQL

使用 PDO 及其預(yù)處理語句功能。

在 PHP 中,有很多方式來連接到一個 MySQL 數(shù)據(jù)庫。PDO(PHP 數(shù)據(jù)對象)是其中最新且最健壯的一種。 PDO 跨多種不同類型數(shù)據(jù)庫有一個一致的接口,使用面向?qū)ο蟮姆绞?,支持更多的新?shù)據(jù)庫支持的特性。

你應(yīng)該使用 PDO 的預(yù)處理語句函數(shù)來幫助防范 SQL 注入攻擊。 使用函數(shù) bindValue 來確保你的 SQL 免于一級 SQL 注入攻擊。 (雖然并不是 100% 安全的,查看進一步閱讀獲取更多細節(jié)。) 在以前,這必須使用一些「魔術(shù)引號(magic quotes)」函數(shù)的組合來實現(xiàn)。PDO 使得那堆東西不再需要。

示例

<?php
try{
    // 新建一個數(shù)據(jù)庫連接
    // You'll probably want to replace hostname with localhost in the first parameter.
    // The PDO options we pass do the following:
    // \PDO::ATTR_ERRMODE enables exceptions for errors.  This is optional but can be handy.
    // \PDO::ATTR_PERSISTENT disables persistent connections, which can cause concurrency issues in certain cases.  See "Gotchas".
    // \PDO::MYSQL_ATTR_INIT_COMMAND alerts the connection that we'll be passing UTF-8 data.
    // This may not be required depending on your configuration, but it'll save you headaches down the road
    // if you're trying to store Unicode strings in your database.  See "Gotchas".
    $link = new \PDO(   'mysql:host=your-hostname;dbname=your-db', 
                        'your-username', 
                        'your-password', 
                        array(
                            \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, 
                            \PDO::ATTR_PERSISTENT => false, 
                            \PDO::MYSQL_ATTR_INIT_COMMAND => 'set names utf8mb4'
                        )
                    );

    $handle = $link->prepare('select Username from Users where UserId = ? or Username = ? limit ?');

    // PHP bug: if you don't specify PDO::PARAM_INT, PDO may enclose the argument in quotes.
    // This can mess up some MySQL queries that don't expect integers to be quoted.
    // See: https://bugs.php.net/bug.php?id=44639
    // If you're not sure whether the value you're passing is an integer, use the is_int() function.
    $handle->bindValue(1, 100, PDO::PARAM_INT);
    $handle->bindValue(2, 'Bilbo Baggins');
    $handle->bindValue(3, 5, PDO::PARAM_INT);

    $handle->execute();

    // Using the fetchAll() method might be too resource-heavy if you're selecting a truly massive amount of rows.
    // If that's the case, you can use the fetch() method and loop through each result row one by one.
    // You can also return arrays and other things instead of objects.  See the PDO documentation for details.
    $result = $handle->fetchAll(\PDO::FETCH_OBJ);

    foreach($result as $row){
        print($row->Username);
    }
}
catch(\PDOException $ex){
    print($ex->getMessage());
}
?>

陷阱

  • 當(dāng)綁定整型變量時,如果不傳遞 PDO::PARAM_INT 參數(shù)有事可能會導(dǎo)致 PDO 對數(shù)據(jù)加引號。 這會搞壞特定的 MySQL 查詢。查看該 bug 報告。

  • 未使用 set names utf8mb4 作為首個查詢,可能會導(dǎo)致 Unicode 數(shù)據(jù)錯誤地存儲進數(shù)據(jù)庫,這依賴于你的配置。 如果你絕對有把握你的 Unicode 編碼數(shù)據(jù)不會出問題,那你可以不管這個。

  • 啟用持久連接可能會導(dǎo)致怪異的并發(fā)相關(guān)的問題。 這不是一個 PHP 的問題,而是一個應(yīng)用層面的問題。只要你仔細考慮了后果,持久連接一般會是安全的。 查看 Stack Overfilow 這個問題

  • 即使你使用了 set names utf8mb4,你也得確認實際的數(shù)據(jù)庫表使用的是 utf8mb4 字符集!

  • 可以在單個 execute() 調(diào)用中執(zhí)行多條 SQL 語句。 只需使用分號分隔語句,但注意這個 bug,在該文檔所針對的 PHP 版本中還沒修復(fù)。

  • Laruence:PDOStatement::bindParam 的一個陷阱

進一步閱讀

上一篇:自動加載類下一篇:存儲密碼