使用 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ù)。