|
|
今天我來系統地學習一下PDO |
巨大八爪鱼
武林盟主 二十一级
|
Floor 1
Posted at: 5/30/15 19:22
操作系統:Fedora 21 PHP版本:最新的5.6.9 開發工具:gedit
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 2
Posted at: 5/30/15 19:23
本帖負責收集筆記。
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 3
Posted at: 5/30/15 19:25
<?php include_once("conn.php"); ?> <!doctype html> <html> <head> <meta charset="utf-8"> <title>PDO Learning</title> </head> <body> <?php ?> </body> </html>
最基本的HTML5頁面代碼,好難記。。。
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 4
Posted at: 5/30/15 19:26
回復:3樓 不過也比HTML4好記多了。 HTML4一上來就是: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns=" http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 5
Posted at: 5/30/15 19:28
首先,連接數據庫。 $db = new PDO("mysql:host=localhost;dbname=test", "php", "it"); 密碼先填寫一個錯誤的,提示:
Fatal error: Uncaught exception 'PDOException' with message
'SQLSTATE[HY000] [1045] Access denied for user 'php'@'localhost' (using
password: YES)' in /var/www/html/temp/11330/conn.php:4
Stack trace:
#0 /var/www/html/temp/11330/conn.php(4):
PDO->__construct('mysql:host=loca...', 'php', 'it')
#1 /var/www/html/temp/11330/index.php(2):
include_once('/var/www/html/t...')
#2 {main}
thrown in /var/www/html/temp/11330/conn.php on line 4
所以必須要加try-catch塊來處理這個錯誤
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 6
Posted at: 5/30/15 19:29
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 7
Posted at: 5/30/15 19:32
function display_exception($msg) { echo $msg; } set_exception_handler("display_exception"); $db = new PDO("mysql:host=localhost;dbname=test", "php", "it");
exception 'PDOException' with message 'SQLSTATE[HY000] [1045] Access
denied for user 'php'@'localhost' (using password: YES)' in
/var/www/html/temp/11330/conn.php:8
Stack trace:
#0 /var/www/html/temp/11330/conn.php(8):
PDO->__construct('mysql:host=loca...', 'php', 'it')
#1 /var/www/html/temp/11330/index.php(2):
include_once('/var/www/html/t...')
#2 {main}
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 8
Posted at: 5/30/15 19:33
try { $db = new PDO("mysql:host=localhost;dbname=test", "php", "it"); } catch (PDOException $e) { echo $e->getMessage(); }
SQLSTATE[HY000] [1045] Access denied for user 'php'@'localhost' (using password: YES)
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 9
Posted at: 5/30/15 19:39
try { $db = new PDO("mysql:host=localhost;dbname=test", "php", "it"); } catch (PDOException $e) { trigger_error("Failed connecting to the database server.", E_USER_ERROR); }
Fatal error: Failed connecting to the database server. in /var/www/html/temp/11330/conn.php on line 7
|
張樹人
初级工程师 九级
|
Floor 10
Posted at: 5/30/15 19:39
回復:3樓 標準的寫法是「<!DOCTYPE html>」 「DOCTYPE」是大寫
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 11
Posted at: 5/30/15 19:39
try { $db = new PDO("mysql:host=localhost;dbname=test", "php", "it"); } catch (PDOException $e) { trigger_error($e->getMessage(), E_USER_ERROR); }
Fatal error: SQLSTATE[HY000] [1045] Access denied for user 'php'@'localhost' (using password: YES) in /var/www/html/temp/11330/conn.php on line 7
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 12
Posted at: 5/30/15 19:40
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 13
Posted at: 5/30/15 19:40
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 14
Posted at: 5/30/15 19:42
接下來研究如何建立持久連接,這個我還從來沒學過。。。
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 15
Posted at: 5/30/15 19:43
PHP手冊上說,建立數據庫持久連接可以大幅度提高性能。
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 16
Posted at: 5/30/15 19:43
資料庫! 不是數據庫(大陸說法)!
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 17
Posted at: 5/30/15 19:57
$dbh = null; 這個相當於原來的mysql_close();
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 18
Posted at: 5/30/15 19:58
人家官方文檔都用$dbh,所以我也用$dbh吧。。。
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 19
Posted at: 5/30/15 20:01
try { $dbh = new PDO("mysql:host=localhost;dbname=test", "php", DB_PW, array(PDO::ATTR_PERSISTENT => true)); } catch (PDOException $e) { trigger_error($e->getMessage(), E_USER_ERROR); }
// NO OUTPUT
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 20
Posted at: 5/30/15 20:05
PDO::ATTR_PERSISTENT mysql:host=localhost;dbname=test 這兩個需要記住
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 21
Posted at: 5/30/15 20:53
獲取單條記錄
$id = (int)@$_GET["i"]; if ($id < 1) { $id = 1; } $sql = "SELECT ItemName, ItemAddress FROM WiFiHotSpots WHERE ItemID = {$id}"; $stmt = $dbh->query($sql); // use $stmt instead of $rs or $result $row = $stmt->fetch(); echo "<b>" . $row[0] . "</b>: " . $row["ItemAddress"];
輸出:
7th Brigade Park, Chermside: Delaware St
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 22
Posted at: 5/30/15 20:55
獲取多條記錄,並循環邊歷記錄集 <?php $sql = "SELECT ItemName, ItemAddress FROM WiFiHotSpots"; $stmt = $dbh->query($sql); // use $stmt instead of $rs or $result foreach ($stmt as $row) { echo "<p><b>" . $row[0] . "</b>: " . $row["ItemAddress"]."</p>"; } ?>
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 23
Posted at: 5/30/15 21:00
循環邊歷記錄集可以用多種方法: 方法一:foreach ($stmt as $row) { 方法二:while ($row = $stmt->fetch()) {
甚至還可以指定次數: for ($i = 0; $i < 4 && $row = $stmt->fetch(); $i++) { echo "<p><b>" . $row[0] . "</b>: " . $row["ItemAddress"]."</p>"; }
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 24
Posted at: 5/30/15 21:01
while ($row = $stmt->fetch()) { 就相當於原來的: while ($row = mysql_fetch_array($rs)) {
for ($i = 0; $i < 4 && $row = $stmt->fetch(); $i++) { 相當於 for ($i = 0; $i < 4 && $row = mysql_fetch_array($rs); $i++) {
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 25
Posted at: 5/30/15 21:03
foreach ($stmt as $row) { 只能遍歷整個記錄集,要想指定次數就得改用$row = $stmt->fetch();
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 26
Posted at: 5/30/15 21:11
從外部獲取字符串參數並傳入SQL查詢中: <?php if (isset($_GET["name"])) { $name = trim($_GET["name"]); // 去掉字符串兩邊的空格 $name = $dbh->quote($name); // 這個大致相當於原來的用於防止SQL隱碼攻擊的mysql_real_escape_string函數,但是這個函數兩邊自動加上了單引號 //echo $name; } else { $name = "Annerley Library Wifi"; } $sql = "SELECT * FROM WiFiHotSpots WHERE ItemName = {$name}"; //注意不能再加單引號了 $stmt = $dbh->query($sql); $row = $stmt->fetch(); echo "(" . $row["ItemLatitude"] . ", " . $row["ItemLongitude"] . ")"; ?>
輸出(-27.3739664, 153.078323)
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 27
Posted at: 5/30/15 21:15
回復:26樓 看PHP官方文檔下面的內容吧:
PDO::quote() places quotes around the input string (if
required) and escapes special characters within the input string, using a
quoting style appropriate to the underlying driver.
If you are using this function to build SQL statements, you are
strongly recommended to use
PDO::prepare() to prepare SQL statements with bound
parameters instead of using PDO::quote() to interpolate
user input into an SQL statement. Prepared statements with bound parameters
are not only more portable, more convenient, immune to SQL injection, but
are often much faster to execute than interpolated queries, as both the
server and client side can cache a compiled form of the query.
Not all PDO drivers implement this method (notably PDO_ODBC). Consider
using prepared statements instead.
因此26樓所屬的方法機不推薦使用,應該改用prepare+bind+execute方法。
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 28
Posted at: 5/30/15 21:16
而且,不是所有數據庫都兼容$dbh->quote
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 29
Posted at: 5/30/15 21:19
改進後的26樓代碼: if (isset($_GET["name"])) { $name = trim($_GET["name"]); } else { $name = "Annerley Library Wifi"; }
$sql = "SELECT * FROM WiFiHotSpots WHERE ItemName = ?"; $stmt = $dbh->prepare($sql); $stmt->execute(array($name)); $row = $stmt->fetch(); echo "(" . $row["ItemLatitude"] . ", " . $row["ItemLongitude"] . ")";
|
巨大八爪鱼
武林盟主 二十一级
|
Floor 30
Posted at: 5/30/15 21:20
注意,那個?同樣不能再加單引號
|