关于mysqli_fetch_object()将查询结果存入对象关联数组属性的可行性及内部实现代码的技术问询
关于mysqli_fetch_object的两个问题解答
问题1:能否将查询结果存入对象的关联数组属性$data中?
很遗憾,你描述的这种方式是无法实现的。
mysqli_fetch_object()的设计逻辑是直接将查询结果的每一列映射为对象的同名属性——不管这个属性是否预先在类中定义。它并不会自动把列数据存入你预先声明的$data关联数组里,而是会直接给对象创建(或覆盖)名为forename、surname的属性。
比如你写的这个类:
class objectname { public $data = array(); }
当你执行$object = mysqli_fetch_object($result, "objectname");后,$object会新增$object->forename和$object->surname两个属性,而$data数组还是空的。
替代方案
如果你想把查询结果统一存入$data属性,有两种常用方法:
方法1:手动映射数组
先通过mysqli_fetch_assoc()拿到关联数组,再手动赋值给对象的$data:
class objectname { public $data = []; } // 先获取查询结果的关联数组 $rowData = mysqli_fetch_assoc($result); // 实例化对象并赋值 $object = new objectname(); $object->data = $rowData; // 现在可以通过$object->data["forename"]访问数据了 echo $object->data["forename"];
方法2:利用魔术方法__set()
在类中定义__set()魔术方法,当mysqli_fetch_object()尝试给未定义的属性赋值时,自动把键值对存入$data数组:
class objectname { public $data = []; public function __set($propertyName, $value) { // 把mysqli要赋值的属性存入$data数组 $this->data[$propertyName] = $value; } } $object = mysqli_fetch_object($result, "objectname"); // 此时$data数组中就会有forename和surname键 echo $object->data["forename"];
注意:如果类中已经预先定义了$forename这类属性,mysqli_fetch_object()会直接给该属性赋值,不会触发__set()方法。
问题2:mysqli_fetch_object()是如何填充对象的?为何能修改私有变量?
这其实是PHP扩展的特性——mysqli是用C语言实现的PHP扩展,它操作对象的方式和纯PHP代码完全不同:
- 实例化对象:当你传入类名时,扩展会调用类的无参构造函数创建对象(如果构造函数需要参数,会直接报错)。
- 绕过访问控制赋值:扩展会直接操作对象的内部属性存储结构,完全绕过PHP的访问修饰符检查(public/protected/private)。也就是说,不管属性的访问权限是什么,只要查询结果的列名和属性名一致,扩展就会直接给这个属性赋值。
举个例子验证这个特性:
class User { private $surname; public function getSurname() { return $this->surname; } } // 假设$result中有surname列 $user = mysqli_fetch_object($result, "User"); echo $user->getSurname(); // 会输出查询到的surname值,哪怕它是private属性
这种行为看起来违反了PHP的面向对象规则,但这是因为扩展可以直接访问对象的底层内存结构,不需要通过PHP的访问控制逻辑。
内容的提问来源于stack exchange,提问作者shuunenkinenbi
相关产品推荐
相关产品推荐

