A. php如何獲得 pdo 查詢結果 列名
回調函數。
1.快取一行
FetchColumn是為應用程序取得一個僅包含單列的數據,代碼如下:
$u = $db->query(「SELECT id FROM users WHERE login=
『login』 AND password=『password』」);
fetch(PDO::FETCH_COLUMN)
if ($u->fetchColumn()) { //返回一個字元串
//登錄成功
} else {
//驗證失敗
}
?>
2.取得一個標准對象
還可以將取得的一行作為一個標准類stdClass的對象實例,其中列名=屬性名。
$res = $db->query(「SELECT * FROM foo」);
while ($obj = $res->fetch(PDO::FETCH_OBJ)) {
// $obj == instance of stdClass
}
?>
3.存取為一個類
PDO允許將結果保存為一個類,例子如下:
$res = $db->query(「SELECT * FROM foo」);
$res->setFetchMode(
PDO::FETCH_CLASS,
「className」,
array(『optional』=『Constructor Params』)
);
while ($obj = $res->fetch()) {
// $obj == instance of className
}
?>
4.從一個類取得常量
PDO允許查詢的結果可以被用來生成一個目的類。
$res = $db->query(「SELECT * FROM foo」);
$res->setFetchMode(
PDO::FETCH_CLASS |
PDO::FETCH_CLASSTYPE
);
while ($obj = $res->fetch()) {
// $obj == instance of class who』s name is
// found in the value of the 1st column
}
?>
5.存取為一個對象
PDO還允許獲取數據到一個已經存在的對象。
$u = new userObject;
$res = $db->query(「SELECT * FROM users」);
$res->setFetchMode(PDO::FETCH_INTO, $u);
while ($res->fetch()) {
// 取得的記錄集將放在$u這個對象變數中,在此顯示
}
?>
6.存取為關聯數據
PDO實現了迭代器(Iteator)介面,允許一個方法實現迭代的功能。
$res = $db->query(
「SELECT * FROM users」,
PDO::FETCH_ASSOC
);
foreach ($res as $row) {
// $row是一個關聯數組,可以直接顯示,如$row['id']
}
?>
7.fetchAll()方法
PDO也提供了和ADODB類似的fetchAll()方法,它允許從一個結果集中取得數據,然後放於關聯數組中。
$db->setAttribute(PDO::ATTR_CASE, PDO::CASE_UPPER);
$qry = 「SELECT * FROM users」;
$res = $db->query($qry)->fetchAll(PDO::FETCH_ASSOC);
?>
或者獲取到索引數組里:
$res = $db->query("SELECT * FROM foo");
$result_arr = $res->fetchAll();
print_r($result_arr);
?>
數字索引數組比較浪費資源,請盡量使用關聯數組,這樣可以在內存中使用相當密集的大型結果集。
相關說明如下:
setAttribute()方法用於設置部分屬性,主要屬性有:PDO::ATTR_CASE、PDO::ATTR_ERRMODE等,這里需要設置的是PDO::ATTR_CASE,就是使用關聯索引獲取數據集時,關聯索引是大寫還是小寫,有如下幾個選擇:
PDO::CASE_LOWER——強制列名是小寫;
PDO::CASE_NATURAL——列名按照原始的方式;
PDO::CASE_UPPER——強制列名為大寫。
我們使用setFetchMode方法來設置獲取結果集的返回值的數據類型,類型有:
PDO::FETCH_ASSOC——關聯數組形式;
PDO::FETCH_NUM——數字索引數組形式;
PDO::FETCH_BOTH——兩種數組形式都有,這是默認的;
PDO::FETCH_OBJ——按照對象的形式,類似於以前的 mysql_fetch_object()。
當然,一般情況下,我們使用PDO::FETCH_ASSOC取得關聯數組。具體使用哪種類型,應按照自己的實際應用選擇。
8.fetchColumn()方法
如果想獲取指定記錄里的一個欄位結果,則可以使用PDOStatement::fetchColumn()。
$rs = $db->query("SELECT COUNT(*) FROM foo");
$col = $rs->fetchColumn();
echo $col;
?>
一般使用fetchColumn()方法進行count統計,對某些只需要單欄位的記錄可以很好地操作。
9.回調函數
PDO還規定在每一個fetch模式下,經過處理後的結果中使用一個回調函數。
function draw_message($subject,$email) { … }
$res = $db->query(「SELECT * FROM msg」);
$res->fetchAll(PDO::FETCH_FUNC,「draw_message」);
?>
10.直接查詢的問題
直接使用Query查詢行每次都會直接提交給資料庫,如果查詢較多,每次頻頻查詢將導致效率降低。
另外,在安全問題上,沒有過濾一些特殊字元容易產生SQL注入。
11.過濾字元
下面我們來看看如何使用PDO進行過濾引起SQL注入的方法,即過濾特殊字元。我們在PDO中使用quote()方法,使用例子如下:
$query = 「SELECT * FROM users WHERE
login=「.$db->quote($_POST[『login』]).」
AND
passwd=「.$db->quote($_POST[『pass』]);
12.事務處理
PDO驅動程序支持所有的事務資料庫,並且PDO提供更簡便的方法,如下:
$db->beginTransaction();
if ($db->exec($qry) === FALSE) {
$db->rollback();
}
$db->commit();
?>
13.執行一個批處理事務
在下面的示例中,假設我們為一個新雇員創建一組條目,這個雇員有一個ID號,即23。除了輸入這個雇員的基本數據外,還需要記錄雇員的薪水。分別完成兩個更新很簡單,但通過將這兩個更新包括在beginTransaction()和commit()調用中,就可以保證在更改完成之前,其他人無法看到更改。如果發生了錯誤,catch塊可以回滾事務開始以來發生的所有更改,並列印出一條錯誤消息。代碼內容如下:
try {
$dbh = new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2',
array(PDO_ATTR_PERSISTENT => true));
echo "Connected\n";
$dbh->setAttribute(PDO_ATTR_ERRMODE, PDO_ERRMODE_EXCEPTION);
$dbh->beginTransaction();
$dbh->exec("insert into staff (id, first, last)
values (23, 'Joe', 'Bloggs')");
$dbh->exec("insert into salarychange (id, amount, changedate)
values (23, 50000, NOW())");
$dbh->commit();
} catch (Exception $e) {
$dbh->rollBack();
echo "Failed: " . $e->getMessage();
}
?>
B. 我的php裡面有php_pdo.dll,打開網頁還是出這個錯:Fatal error: Class 'PDO' not found in
你前面引用這個類所在的文件了么?
include_once("PDO.php");
並不是存在PDO.dll就可以使用的,那隻是PHP環境支持你調用了
類還需要自己寫或者引入
C. PHP的PDO使用:
引入smarty.class.php類沒有
$pdo = new PDO("mysql:host=localhost;dbname=newsdb;charset=utf8","root","root");
最好定義一下字元集
D. PHP 的 pdo 方法,怎麼返回欄位名
PDO是PDO, Mysqli是Mysqli,我們沒辦法要求PDO像Mysqli保持一樣的結構和設計。
也許你會覺得mysqli的fetch_field很方便,但是實際上這個方法的使用概率極低,因為通常會讀出表的所有欄位信息並緩存起來,而不是總是進行欄位查詢。
表現最明顯的框架如Cakephp,當你用直接編輯數據表的方法增加了一個新欄位之後數據並不會被保存到這個欄位中,必須先清除緩存的數據表信息才行。
通過閱讀不同的PHP框架,我們可以發現極少會有框架需要開發人員直接調用PDO或者mysqli對象去執行sql,它們往往將其通過DbAdapter之類的介面進行封裝。我建議你思考這樣做的好處然後優化自己的代碼結構。你問題中的這個行為通常也不需要封裝在db對象中,一般是在Table對象處理,例如
class Table {
protected $_tableName;
public function __construct($tableName);
protected function _readFieldsPrototype();
protected function _getCachedFieldsPrototype();
public function getFieldPrototype($filed);
}
E. 為什麼 PHP 應該使用 PDO 方式訪問資料庫
很多程序員都學習過如何使用 MySQL 或 MySQLi 擴展訪問資料庫。在 PHP 5.1 中,有一個更好的方法。PHP Data Objects(PDO) 提供了很多預處理語句的方法,且使用對象將使你的工作更有成效!
PDO 介紹
「PDO – PHP Data Objects – 是一個對多種資料庫提供統一操作方法的資料庫訪問層。」
它並不具備資料庫特有的語法,但它將使切換資料庫和平台更加容易,多數情況下,只需要簡單修改鏈接字元串。
這並非一篇完整教導如何使用SQL的教程。它重要為那些現今仍在使用 mysql 或 mysqli 擴展的人,幫助他們躍至更具可移植性和強力的 PDO。
資料庫支持
此擴展可以使用 PDO 驅動編寫過的所有資料庫。在本文書寫時,下面的資料庫支持已經實現:
PDO_DBLIB ( FreeTDS / Microsoft SQL Server / Sybase )
PDO_FIREBIRD ( Firebird/Interbase 6 )
PDO_IBM ( IBM DB2 )
PDO_INFORMIX ( IBM Informix Dynamic Server )
PDO_MYSQL ( MySQL 3.x/4.x/5.x )
PDO_OCI ( Oracle Call Interface )
PDO_ODBC ( ODBC v3 (IBM DB2, unixODBC and win32 ODBC) )
PDO_PGSQL ( PostgreSQL )
PDO_SQLITE ( SQLite 3 and SQLite 2 )
PDO_4D ( 4D )
你的系統不會也不必支持所有上面的驅動;下面是一個快速檢查所支持資料庫的方法:
1 print_r(PDO::getAvailableDrivers());
連接
不同資料庫的連接方法可能稍有不同,下面是一些較為流行的資料庫連接方法。你將注意到,雖然資料庫類型不同,前三種資料庫的連接方式是相同的——而 SQLite 使用自己的語法。
Connection String
01 try {
02 # MS SQL Server andSybase with PDO_DBLIB
03 $DBH = newPDO("mssql:host=$host;dbname=$dbname, $user, $pass");
04 $DBH = newPDO("sybase:host=$host;dbname=$dbname, $user, $pass");
05
06 # MySQL with PDO_MYSQL
07 $DBH = newPDO("mysql:host=$host;dbname=$dbname", $user, $pass);
08
09 # SQLite Database
10 $DBH = newPDO("sqlite:my/database/path/database.db");
11 }
12 catch(PDOException $e) {
13 echo$e->getMessage();
14 }
注意 try/catch 塊——你應該總是使用 try/catch 包裝你的 PDO 操作,並使用異常機制——這里只是簡單的示例。通常,你只需要一個連接——有很多可以教你語法的列表。 $DBH 代表「資料庫句柄」,這將貫穿全文。
通過將句柄設置為 NULL,你可以關閉任一連接。
1 # close the connection
2 $DBH = null;
你可以在PHP.net找到更多資料庫特定選項和/或其它資料庫連接字元串的信息。
異常與 PDO
PDO 可以使用異常處理錯誤,這意味著你的所有 PDO 操作都應當包裝在一個 try/catch 塊中。你可以通過設定錯誤模式屬性強制 PDO 在新建的句柄中使用三種錯誤模式中的某一個。下面是語法:
1 $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
2 $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
3 $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
無論你設定哪個錯誤模式,一個錯誤的連接總會產生一個異常,因此創建連接應該總是包裝在 try/catch 塊中。
PDO::ERRMODE_SILENT
這是默認的錯誤模式。如果你使用這個模式,你將得使用同 mysql 或 mysqli 擴展一樣的方法差錯。其它兩種模式更適合 DRY 編程。
PDO::ERRMODE_WARNING
此方法將會發出一個標准PHP警告,並允許程序繼續運行。這對調試很有幫助。
PDO::ERRMODE_EXCEPTION
這是多數情況下你所希望的方式。它生成異常,允許你更容易的處理錯誤,隱藏可能導致它人了解你系統的信息。下面是一個充分利用異常的示例:
01 # connect to the database
02 try {
03 $DBH = newPDO("mysql:host=$host;dbname=$dbname", $user, $pass);
04 $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
05
06 # UH-OH! Typed DELECT instead of SELECT!
07 $DBH->prepare('DELECT name FROM people');
08 }
09 catch(PDOException $e) {
10 echo"I'm sorry, Dave. I'm afraid I can't do that.";
11 file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);
12 }
在 select 語句中有一個故意留下的錯誤;這將導致一個異常。異常錯誤細節保存至一個 log 文件,並生成一段友好的(或不怎麼友好的)信息於用戶。
插入和更新
插入新數據,更新已存數據是一種非常常見的資料庫操作。使用 PDO,這通常需要兩個步驟。本節中所述的所有內容對更新和插入都有效。
這里有一個最基本的插入示例:
1 # STH means "Statement Handle"
2 $STH = $DBH->prepare("INSERT INTO folks ( first_name ) values ( 'Cathy' )");
3 $STH->execute();
你也可以使用 exec() 完成相同的操作,這將減少調用。多數情況下,你會使用調用多的方法,以充分利用語句預處理的優勢。即使你只用它一次,使用語句預處理,幫助你保護你的 SQL 免於注入攻擊。
預處理語句
使用語句預處理將幫助你免於SQL注入攻擊。
一條預處理語句是一條預編譯的 SQL 語句,它可以使用多次,每次只需將數據傳至伺服器。其額外優勢在於可以對使用佔位符的數據進行安全處理,防止SQL注入攻擊。
你通過在 SQL 語句中使用佔位符的方法使用預處理語句。下面是三個例子:一個沒有佔位符,一個使用無名佔位符,一個使用命名佔位符。
1 # no placeholders - ripe for SQL Injection!
2 $STH = $DBH->("INSERT INTO folks (name, addr, city) values ($name, $addr, $city)");
3
4 # unnamed placeholders
5 $STH = $DBH->("INSERT INTO folks (name, addr, city) values (?, ?, ?);
6
7 # named placeholders
8 $STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");
你希望避免第一種方法。選擇命名我無名佔位符將會對你對語句中數據的設置產生影響。
無名佔位符
01 # assign variables to each place holder, indexed 1-3
02 $STH->bindParam(1, $name);
03 $STH->bindParam(2, $addr);
04 $STH->bindParam(3, $city);
05
06 # insert one row
07 $name = "Daniel"
08 $addr = "1 Wicked Way";
09 $city = "Arlington Heights";
10 $STH->execute();
11
12 # insert another row with different values
13 $name = "Steve"
14 $addr = "5 Circle Drive";
15 $city = "Schaumburg";
16 $STH->execute();
這里有兩步。首先,我們對各個佔位符指定變數(2-4行)。然後,我們對各個佔位符指定數據,並執行語句。要發送另一組數據,只需改變這些變數的值並再次執行語句。
這種方法看上去對擁有很多參數的語句很笨拙吧?的確。然而,當數據保存於數組中時,這非常容易簡略:
1 # the data we want to insert
2 $data = array('Cathy', '9 Dark and Twisty Road', 'Cardiff');
3
4 $STH = $DBH->("INSERT INTO folks (name, addr, city) values (?, ?, ?);
5 $STH->execute($data);
容易吧!
數組中的數據按順序填入佔位符中。 $data[0]是第一個,$data[1]是第二個,依次。不過,要是數組中數據的次序不正確,這將不能正常運行,你需要先對數組排序。
命名佔位符
你可能已經開始猜測語法了,不過下面就是示例:
1 # the first argument is the named placeholder name - notice named
2 # placeholders always start with a colon.
3 $STH->bindParam(':name', $name);
你可以看使用快捷方式,但它需使用關聯數組。下面是示例:
1 # the data we want to insert
2 $data = array( 'name' => 'Cathy', 'addr' => '9 Dark and Twisty', 'city' => 'Cardiff' );
3
4 # the shortcut!
5 $STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");
6 $STH->execute($data);
數組中的鍵不需要以冒號開頭,但其它部分需要同佔位符匹配。如果你有一個二維數組,你只需遍歷它,並對遍歷的每個數組執行語句。
命名佔位符的另一個好的功能是直接將對象插入到你的資料庫中,只要屬性同命名欄位匹配。下面是一個示例對象,以及如何將它插入到資料庫中的示例:
01 # a simple object
02 class person {
03 public $name;
04 public $addr;
05 public $city;
06
07 function __construct($n,$a,$c) {
08 $this->name = $n;
09 $this->addr = $a;
10 $this->city = $c;
11 }
12 # etc ...
13 }
14
15 $cathy = new person('Cathy','9 Dark and Twisty','Cardiff');
16
17 # here's the fun part:
18 $STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");
19 $STH->execute((array)$cathy);
通過在執行時將對象轉換為數組,輸將將會同數組的鍵一樣對待。
F. php連接資料庫關於PDO類和PDOStatement類的區別是什麼
這代表兩個不同的對象,看一下PDO::query()的定義:
public PDOStatement PDO::query ( string $statement )
可以知道query返回的結果是PDOStatement實例對象,那麼你至少可以知道PDOStatement可以用來操作結果集了。
看一下PDOStatement類有哪些方法:
http://php.net/manual/zh/class.pdostatement.php
發現有fetch,fetchAll等熟悉的功能,不是么?
然後再來看看PDO::prepare()方法
public PDOStatement PDO::prepare ( string $statement [, array $driver_options = array() ] )
它也是返回的PDOStatement,按照手冊的說法,PDOStatement代表一條預處理語句,並在該語句被執行後代表一個相關的結果集。
也就是說,如果你通過PDO::query()直接查詢,那麼返回的PDOStatement就表示一個結果集。
如果你通過PDO::prepare()查詢,實際上並未執行sql,而是得到一個預處理語句(PDOStatement),然後你調用PDOStatement::execute()方法真正執行。