上一篇文章已经解释了为什么您的示例没有按预期工作。但是,在使用数据库时有一些很好的编码实践,这对于提高应用程序的安全性很重要(即防止 SQL 注入)。
以下示例旨在展示其中的一些实践,并假设 PHP 5.2 和 MySQL 5.1。(请注意,所有文件和数据库条目都使用 UTF-8 编码存储。)
本例中使用的数据库名为test
,创建表如下:
CREATE TABLE `test`.`entries` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`data` VARCHAR( 100 ) NOT NULL
) ENGINE = InnoDB CHARACTER SET utf8 COLLATE utf8_bin
(请注意,编码设置为utf8_bin
。)
它遵循用于两者的 php 代码,添加新条目和创建 JSON:
<?
$conn = new PDO('mysql:host=localhost;dbname=test','root','xxx');
$conn->exec("SET NAMES 'utf8'"); // Enable UTF-8 charset for db-communication ..
if(isset($_GET['add_entry'])) {
header('Content-Type: text/plain; charset=UTF-8');
// Add new DB-Entry:
$data = $conn->quote($_GET['add_entry']);
if($conn->exec('INSERT INTO `entries` (`data`) VALUES ('.$data.')')) {
$id = $conn->lastInsertId();
echo 'Created entry '.$id.': '.$_GET['add_entry'];
} else {
$info = $conn->errorInfo();
echo 'Unable to create entry: '. $info[2];
}
} else {
header('Content-Type: text/json; charset=UTF-8');
// Output DB-Entries as JSON:
$entries = array();
if($res = $conn->query('SELECT * FROM `entries`')) {
$res->setFetchMode(PDO::FETCH_ASSOC);
foreach($res as $row) {
$entries[] = $row;
}
}
echo json_encode($entries);
}
?>
$conn->quote(..)
在将数据传递到数据库之前,请注意该方法的用法。如上一篇文章所述,使用准备好的语句会更好,因为它们已经完成了整个转义。因此,如果我们这样写会更好:
$prepStmt = $conn->prepare('INSERT INTO `entries` (`data`) VALUES (:data)');
if($prepStmt->execute(array('data'=>$_GET['add_entry']))) {...}
代替
$data = $conn->quote($_GET['add_entry']);
if($conn->exec('INSERT INTO `entries` (`data`) VALUES ('.$data.')')) {...}
结论:对存储或传输给用户的所有字符数据使用 UTF-8 是合理的。它使国际化Web应用程序的开发更加容易。为确保用户输入正确发送到数据库,使用转义函数是个好主意。否则,使用准备好的语句使生活和开发更加容易,并且进一步提高了您的应用程序安全性,因为 SQL 注入被阻止了。