當使用從資料庫查詢返回的 stdClass 物件時,特別是
$object = mysql_fetch_object($result)
如果欄位名稱中包含 '.',則可能會遇到賦值問題。
例如:`user.id`
要解決此問題,您可以在賦值時使用大括號和單引號。
以
$myObject->user_id = $object->user.id;
取代
$myObject->user_id = $object->{'user.id'};
(PHP 4, PHP 5)
mysql_fetch_object — 將結果列擷取為物件
這個擴充功能在 PHP 5.5.0 中已被棄用,並在 PHP 7.0.0 中被移除。建議改用 MySQLi 或 PDO_MySQL 擴充功能。另請參閱 MySQL:選擇 API 指南。此函式的替代方案包括:
mode
為 PDO::FETCH_OBJ
的 PDOStatement::fetch()返回一個物件,其屬性對應於擷取的資料列,並將內部資料指標向前移動。
result
正在評估的結果 資源。此結果來自對 mysql_query() 的呼叫。
class_name
要實例化、設定屬性並返回的類別名稱。如果未指定,則返回 stdClass 物件。
params
一個可選的 陣列 參數,用於傳遞給 class_name
物件的建構函式。
範例 #1 mysql_fetch_object() 範例
<?php
mysql_connect("hostname", "user", "password");
mysql_select_db("mydb");
$result = mysql_query("select * from mytable");
while ($row = mysql_fetch_object($result)) {
echo $row->user_id;
echo $row->fullname;
}
mysql_free_result($result);
?>
範例 #2 mysql_fetch_object() 範例
<?php
class foo {
public $name;
}
mysql_connect("hostname", "user", "password");
mysql_select_db("mydb");
$result = mysql_query("select name from mytable limit 1");
$obj = mysql_fetch_object($result, 'foo');
var_dump($obj);
?>
注意:效能
速度方面,此函式與 mysql_fetch_array() 相同,幾乎與 mysql_fetch_row() 一樣快(差異微乎其微)。
備註:
mysql_fetch_object() 與 mysql_fetch_array() 類似,差別在於它返回的是一個物件,而不是一個陣列。間接地,這意味著您只能通過欄位名稱來存取資料,而不能通過它們的偏移量(數字是無效的屬性名稱)。
注意:此函式返回的欄位名稱*區分大小寫*。
注意:此函式會將 NULL 欄位設定為 PHP 的
null
值。
當使用從資料庫查詢返回的 stdClass 物件時,特別是
$object = mysql_fetch_object($result)
如果欄位名稱中包含 '.',則可能會遇到賦值問題。
例如:`user.id`
要解決此問題,您可以在賦值時使用大括號和單引號。
以
$myObject->user_id = $object->user.id;
取代
$myObject->user_id = $object->{'user.id'};
如果您使用 mysql_fetch_object 並指定一個類別,則屬性會在建構子執行 *之前* 設定。這通常不是問題,但如果您的屬性是透過 __set() 魔術方法設定的,並且建構子邏輯必須先執行,則可能會造成一些重大問題。
自 PHP 5.2.1 起,這個函式似乎不喜歡傳回空名稱欄位的查詢,例如
select '' from `table`
PHP 會退出,且 mysql_error() 不會傳回錯誤。
計時上的巨大差異可能是由資料庫快取問題引起的。如果 mysql_fetch_object() 是第一個被使用的函式,則快取是空的,但後續呼叫會從查詢快取中取得結果。
回覆 rodolphe dot bodeau at free dot fr
mysql_fetch_object 函式還有另外兩個參數可以使用。
如同手冊所述
mysql_fetch_object( $resource, $class_name, $params ) )
$class_name 和 $params 是選用的。
因此,如果您想在類別中擷取一行,您可以
1) 使用方法和其他內容定義您的 Test 類別。
2) 執行查詢
3) 呼叫
$Object = mysql_fetch_object( $Resource, "Test" );
這樣您就可以使用 $Object 及其方法
請注意您如何在方法中編寫程式碼:在這種情況下,類別用於集中程式碼,它們並不是
真正安全的,因為您可能有額外的資訊
(例如使用 Join 查詢)而沒有方法可以存取它們。
因此,類別需要通用的 get 和 set 方法。
(更多資訊請參閱 O'Rielly PHP 5 手冊中關於通用方法 get 和 set 的使用)
這個小函式會使用 MySQL 請求欄位名稱作為物件參數,將 mysql_fetch_object 結果的內容儲存到物件中。
<?php
function FetchRequestInObject(&$obj, $req)
{
$ReqVars = get_object_vars($req);
foreach ($ReqVars as $ReqName => $ReqValue)
{
if (property_exists($obj, $ReqName))
{
$obj->$ReqName = $ReqValue;
}
}
}
?>
請記住,mysql_fetch_object 區分大小寫,因此請注意您的物件屬性。如有必要,請在 SQL 請求中使用關鍵字 "AS" 來更改欄位名稱。
使用 mysql_fetch_object() 時要注意,它會將所有值都以字串形式返回。
如果您嘗試這樣做
<?
$p = mysql_fetch_object($some_sql);
// 然後嘗試執行類似以下操作
$money = $p->dollars + $p->cents;
?>
您可能會遇到「不支援的運算元類型」錯誤
所以務必將它們都強制轉換為 (int) 型別!
<?php
class Test {
public $go ;
private $id ;
function show() {
return "id: {$this->id} go: {$this->go}" ;
}
function __construct()
{
echo "在 __construct() 中 ". $this->show() ."\n" ;
$this->go = uniqid() ;
}
}
if (! ($res = mysql_query('SELECT * FROM `test`', $db))) {
die('查詢無效: ' . mysql_error() . "\n");
}
while($obj = mysql_fetch_object($res, 'Test') ){
echo "外部 ________ ". $obj->show() ."\n\n";
}
?>
這段程式碼會產生以下結果
在 __construct() 中 id: 1 go: first
外部 ________ id: 1 go: 4845bd99ca2e3
在 __construct() 中 id: 2 go: second
外部 ________ id: 2 go: 4845bd99ca2fd
這表示 __construct() 在使用資料庫資料填滿欄位後才被呼叫,例如,它可以用來將字串轉換為整數。
這個方法提供了一個從資料庫擷取物件的好方法。 正如 Federico at Pomi dot net 提到的,它本身無法正常運作,因為擷取的物件類型不正確,但只要稍微進行類型轉換,它就能完美運作。
<?php
函式 ClassTypeCast(&$obj,$class_type){
if(class_exists($class_type)){
$obj = unserialize(preg_replace("/^O:[0-9]+:\\"[^\"]+\\":/i",
"O:".strlen($class_type).":\\"".$class_type."\\":", serialize($obj)));
}
}
類別 Foo
{
變數 $foo;
變數 $bar;
函式 get_from_db()
{
mysql_connect();
mysql_select_db();
$res = mysql_query("SELECT foo,bar from my_table");
$fetched_object = mysql_fetch_object($res);
ClassTypeCast($fetched_object,"Foo");
$this = $fetched_object;
}
}
?>
這是另一種快速載入變數到 $this 的方法,並且允許介入變數名稱。
單列結果中的所有欄位都會被載入,並可透過 $this->_變數名稱 進行存取。
<?
類別 MyClass{
公開函式 _load($nID) {
$Q = "SELECT * FROM myTable";
if($aTmp = RETURN_Q_ARRAY($Q)) {
$aTmp = $aTmp[0];
$aK =array_keys($aTmp);
foreach($aK as $sK) {
if(!is_numeric($sK)) $this->{"_$sK"}=$aTmp[$sK];
}
回傳 真;
}
回傳 假;
}
}
$o = new MyClass;
$o->_load(1);
echo $o->_id; //1
echo $o->_otherColumn; //otherColumn 值
@Jezze:這個方法也行得通。也適用於靜態方法。
<?php
類別 Foo
{
私有 $FooBar;
公開函式 LoadFromId($Id)
{
$Result = mysql_query('SELECT * FROM foo WHERE Id = ' . $Id);
while($Row = mysql_fetch_object($Result, __CLASS__))
{
print_r($Row);
}
}
}
$Foo = new Foo;
$Foo->LoadAll();
?>
關於 Simon Paridon 和其他人關於 SQL 到 php 透過 mysql_fetch_object 取得結果的問題
任何在資料庫前端(例如 MySQL 的「查詢瀏覽器」)中會失敗的查詢,而且只能透過使用 ` 標記才能運作的查詢,在 PHP 中取得的結果可能難以存取,尤其是在欄位名稱中包含「-」或「 」時。
以 Simon Paridon 的例子來說:無法執行像這樣的查詢
SELECT id, user-id FROM unlucky_naming
只有
SELECT id, `user-id` FROM unlucky_naming
才能運作...
因此,在命名欄位時最好明智一點(例如 user_id)
或者嘗試這樣做
SELECT id, `user-id` AS user_id FROM unlucky_naming
(我還沒在 PHP 中測試過,但我猜測如果你的查詢語句像 "SELECT `foo name` FROM `unlucky naming 2`" 這樣,也會失敗。)
樓下 "amackenz at cs dot uml dot edu" 提到了命名 sum、count 等等,這可能對新手來說是個好提示:透過使用 (my)sql 內建函數來提升 PHP 應用程式的速度,同時節省數據傳輸和處理時間。
在審閱 Eskil Kvalnes 的評論時(2003 年 3 月 4 日 11:59),
當在查詢中使用表格聯結時,顯然需要命名所有欄位,才能讓它與 mysql_fetch_object() 正確運作。我留下了一個疑問,而作為一個新手,這就是我來這裡的原因。我有一個 28 個欄位的表格。使用 LEFT JOIN 執行 SELECT *,在我的測試伺服器上似乎沒有問題。
進一步閱讀後,MYSQL.COM 有以下說明:
* 不允許在 WHERE 子句中使用欄位別名,因為在執行 WHERE 子句時,欄位值可能尚未確定。請參閱 A.5.4 節,關於別名的問題。
* FROM table_references 子句指示要從哪些表格檢索列。如果您指定了多個表格,則表示您正在執行聯結。有關聯結語法的資訊,請參閱 6.4.1.1 節,JOIN 語法。對於指定的每個表格,您可以選擇指定一個別名。
我知道表格和欄位之間存在差異,但這裡似乎有些混淆。
關於先前筆記中提到的結果集中重複欄位名稱的一些說明。
考慮以下關係:
TABLE_A(id, name)
TABLE_B(id, name, id_A)
其中 TABLE_B.id_A 參考 TABLE_A.id。
現在,如果我們這樣聯結這些表格:"SELECT * FROM TABLE_A, TABLE_B WHERE TABLE_A.id = TABLE_B.id_A",結果集看起來像這樣:(id, name, id, name, id_A)。
這裡沒有記錄 mysql_fetch_object 對於這種結果的行為,但很明顯,由於欄位名稱重複,一些數據將會遺失。
正如 Eskil Kvalnes 所述,透過使用欄位別名可以避免這種情況。然而,沒有必要為大型表格上的所有欄位都設定別名,因為以下語法在 MySQL 中是合法的:"SELECT *, TABLE_A.name AS name_a, TABLE_B.name AS name_b FROM TABLE_A, TABLE_B ..."。這將產生格式如下:(id, name, id, name, id_A, name_a, name_b) 的結果集,並且您的數據得以保留。萬歲!
-q
請小心
返回的物件將是一個新的/乾淨的物件。
您不能使用這個函數來替換現有物件的某些屬性,同時保留舊的屬性。
範例
類別 person
{
變數 $name;
變數 $surname;
變數 $doh;
函數 print()
{
print($name." ".$surname);
}
函數 get_from_db()
{
$res=query("select name, surname from ppl where... limit 1");
$this=mysql_fetch_object($res);
}
}
這行不通!當執行 get_from_db() 方法時,您的舊物件將被銷毀...您在 $doh 屬性中找不到任何東西,如果您嘗試呼叫 print() 方法,它會說這個方法不存在。
我建立了一個表格,包含 5 個 INT 欄位和 1000 列隨機整數。
我執行了 100 次查詢
SELECT * FROM bench... (mysql_fetch_object)
查詢時間:5.40725040436
擷取時間:16.2730708122(平均:1.32130565643E-5)
總時間:21.6803212166
SELECT * FROM bench... (mysql_fetch_array)
查詢時間:5.37693023682
擷取時間:10.3851644993(平均:7.48886537552E-6)
總時間:15.7620947361
SELECT * FROM bench... (mysql_fetch_assoc)
查詢時間:5.345921278
擷取時間:10.6170959473(平均:7.64049530029E-6)
總時間:15.9630172253
「注意:就效能速度而言,此函式與 mysql_fetch_array() 相同,幾乎與 mysql_fetch_row() 一樣快(差異微不足道)。」
而且我是一隻企鵝 :)
這樣可能更簡潔一點
$sql = "SELECT * FROM table ";
$result = mysql_query($sql);
$data = array();
while ($row = mysql_fetch_object($result))
$data[] = $row;
這是一個非常簡潔(且成本低)的方法,可以將整個查詢的每個欄位都擷取到一個「寬」表格中。
繁瑣的擷取方式
<?php
$idtable=mysql_connect("localhost","user","pwd");
mysql_select_db("table",$idtable);
$consult=mysql_query("SELECT *
FROM models
ORDER BY Serie,Year ASC");
while($row=mysql_fetch_object($consult)){
$IdLomo=$row->IdLomo;
$Serie=$row->Serie;
$Model=$row->Model;
$Type=$row->Type;
$Year=$row->Year;
$Speed=$row->Speed;
$Power=$row->Power;
$Price=$row->Price;
$Load1=$row->Load1;
$Load2=$row->Load2;
$Load3=$row->Load3;
$Load4=$row->Load4;
$Server=$row->Servier;
$Real=$row->Real;
$Lomo=$row->Lomo;
}
?>
結果產生了 15 個與表格中欄位名稱相同的新變數,我們手動輸入這些變數名稱花了 5 分鐘。但想像一下,如果每一列有 100 個欄位呢!
一種節省時間並獲得相同結果的方法
<?php
$idtable=mysql_connect("localhost","user","pwd");
mysql_select_db("table",$idtable);
$consult=mysql_query("SELECT *
FROM models
ORDER BY Serie,Year ASC");
// 找出欄位數量
$numfields=mysql_num_fields($consult);
// 將欄位名稱放入陣列
for($i=0;$i<$numfields;$i++){
$fieldname[$i]=mysql_field_name($consult, $i);
}
while($row=mysql_fetch_object($consult)){
//最後,將值賦予新的變數
for($i=0;$i<$numfields;$i++){
$$fieldname[$i]=$row->$fieldname[$i];
}
}
?>
補充前一點...
例如從資料庫中取得成員
function getAllMembers () {
$query = "SELECT * FROM people ORDER BY lname";
$result = mysql_query($query);
while($member = mysql_fetch_object($result)){
$members[] = $member;
}
return $members;
}
<br><br>
別忘了宣告陣列。如果您嘗試在呼叫函式後循環瀏覽成員,但沒有事先宣告陣列,您的頁面將會出現非常(非常!)醜陋的錯誤。此外,如果您嘗試在 while 條件內而不是 while 迴圈內將物件添加到成員陣列中,由於最後一次迭代/檢查,您將在陣列中產生一個額外的空白空間。
我發現上面的程式碼有錯誤,沒有將所有記錄添加到陣列中。以下是我使用的程式碼
$command = "SELECT * FROM table ";
$result = mysql_query($command, $link_id);
$num = mysql_num_rows($result);
$clickthru = array();
for ($i = 0; $i <= $num; $i++) {
$clickthru[$i] = array();
$clickthru[$i] = mysql_fetch_array($result);
}
Allen
這是一個允許指定類別名稱的包裝函式。
function &db_fetch_object($set,$className)
{
/* 先取得一般的陣列 */
$row = mysql_fetch_assoc($set);
if ($row === null) return null;
/* 建立物件 */
$obj =& new $className();
/* 將陣列展開並設定物件的實例資料 */
foreach($row as $key => $value)
{
$obj->{$key} = $value;
}
return $obj;
}
class CPerson
{
函式 getFullName()
{
回傳 $this->fname . ' ' . $this->lname;
}
}
$set = mysql_query('SELECT fname,lname FROM person');
while($person =& db_fetch_object($set,'CPerson'))
{
echo $person->getFullName();
}
這個函式的行為有點問題。
如果你的資料表中有包含非變數名稱字元的欄位,例如「-」,mysql_fetch_object 會將「不可能的變數名稱」新增到你的物件中,例如:
物件 (
[user-id] => 7
)
你無法使用 $obj->user-id 正常地存取這個變數,因為變數名稱無效。但是你可以像這樣存取它
$foo = 'user-id';
echo $obj->$foo;
它會正確輸出 7,然而 var_dump($obj->user-id) 會因為某些原因輸出 int(0)。
我在 PHP 4.4.2 中遇到這種情況。