当使用从数据库查询返回的 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指南。此函数的替代方案包括
返回一个对象,其属性对应于获取的行,并将内部数据指针向前移动。
result
正在评估的结果资源。此结果来自对mysql_query()的调用。
class_name
要实例化、设置属性并返回的类的名称。如果未指定,则返回一个stdClass对象。
params
一个可选的数组,用于传递给class_name
对象的构造函数的参数。
返回一个具有字符串属性的对象,这些属性对应于获取的行,如果不再有行,则返回false
。
示例 #1 mysql_fetch_object() 示例
<?php
mysql_connect("主机名", "用户名", "密码");
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("主机名", "用户名", "密码");
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 方法。
(更多信息请参阅 PHP 5 手册 O'Rielly 关于通用 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 "in __construct() ". $this->show() ."\n" ;
$this->go = uniqid() ;
}
}
if (! ($res = mysql_query('SELECT * FROM `test`', $db))) {
die('Invalid query: ' . mysql_error() . "\n");
}
while($obj = mysql_fetch_object($res, 'Test') ){
echo "outside ________ ". $obj->show() ."\n\n";
}
?>
这段代码的结果是
in __construct() id: 1 go: first
outside ________ id: 1 go: 4845bd99ca2e3
in __construct() id: 2 go: second
outside ________ id: 2 go: 4845bd99ca2fd
这意味着 __construct() 方法是在用数据库数据填充字段后调用的,例如,它可以用来将字符串转换为整数。
这种方法提供了一种从数据库中获取对象的好方法。正如 Federico at Pomi dot net 提到的那样,它不能原生工作,因为获取的对象类型不正确,但是通过一个小型的类型转换,它可以完美地工作。
<?php
function 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)));
}
}
class Foo
{
var $foo;
var $bar;
function 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->_variableName 访问。
<?
class MyClass{
public function _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];
}
return true;
}
return false;
}
}
$o = new MyClass;
$o->_load(1);
echo $o->_id; //1
echo $o->_otherColumn; //otherColumn 值
@Jezze:这也适用。也适用于静态方法。
<?php
class Foo
{
private $FooBar;
public function 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 个字段的表。使用 SELECT * 和 LEFT JOIN 等运行查询,它似乎在我的测试服务器上运行没有问题。
在进一步阅读后,MYSQL.COM 有以下内容
* 不允许在 WHERE 子句中使用列别名,因为在执行 WHERE 子句时,列值可能尚未确定。请参阅 A.5.4 节“别名问题”。
* FROM table_references 子句指示要从中检索行的表。如果命名多个表,则正在执行联接。有关联接语法的详细信息,请参见第 6.4.1.1 节“联接语法”。对于每个指定的表,可以选择指定别名。
知道表和字段之间存在差异,这里似乎有些混淆。
关于之前关于结果集中重复字段名称的说明。
考虑以下关系
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
小心
返回的对象将是一个新的/新鲜的对象。
您不能使用此函数替换现有对象的某些属性并保留旧属性。
示例
class person
{
var $name;
var $surname;
var $doh;
function print()
{
print($name." ".$surname);
}
function 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 循环中将对象添加到 members 数组中,则由于最后一次迭代/检查,您会在数组中生成一个额外的空空间。
我发现上面的代码有错误,没有将所有记录添加到数组中。这是我使用的代码
$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;
}
返回 $obj;
}
类 CPerson
{
函数 getFullName()
{
返回 $this->fname . ' ' . $this->lname;
}
}
$set = mysql_query('SELECT fname,lname FROM person');
当 ($person =& db_fetch_object($set,'CPerson'))
{
输出 $person->getFullName();
}
此函数的行为略有疑问。
如果你的表中有一列包含非变量名字符(例如“-”),mysql_fetch_object 将会为你的对象添加“无效的变量名”,例如:
对象(
[user-id] => 7
)
你不能使用 $obj->user-id 正常访问此变量,因为变量名无效。但是你可以这样访问它:
$foo = 'user-id';
输出 $obj->$foo;
它将正确输出 7,而 var_dump($obj->user-id) 由于某种原因会输出 int(0)。
我在 PHP 4.4.2 中遇到了此行为。