如何创建类似Laravel Eloquent、同时支持对象和数组访问的自定义对象
问题原因
User::find(0)返回的是Eloquent模型实例,它同时实现了PHP的ArrayAccess接口和属性读写的魔术方法,因此同时支持对象语法->和数组语法[]访问属性。
而你用到的其他类型天生不支持两种访问:
- 原生
stdClass没有实现ArrayAccess接口,所以用数组语法访问会抛出Cannot use object of type stdClass as array错误 - 原生数组不是对象,没有对应的魔术方法处理对象属性语法的访问,所以用
->访问会报错
实现方案
Laravel项目场景(和User模型同环境)
直接用Laravel官方提供的Illuminate\Support\Fluent类即可,开箱即用支持两种访问方式:
// 实例化对象 $teacher = new \Illuminate\Support\Fluent(); // 两种赋值方式都生效 $teacher->name = "Teacher 1"; $teacher['age'] = 30; // 两种读取方式都生效 echo $teacher['name']; // 输出 Teacher 1 echo $teacher->age; // 输出 30
如果需要更多类似模型的特性,也可以直接继承Illuminate\Database\Eloquent\Model自定义空模型使用。
原生PHP通用场景
如果是非Laravel的原生PHP项目,可以自己实现ArrayAccess接口配合魔术方法达成相同效果,示例代码如下:
class ArrayableObject implements ArrayAccess { // 存储属性的容器 protected $attributes = []; // 处理对象形式的属性读写 public function __get($key) { return $this->attributes[$key] ?? null; } public function __set($key, $value) { $this->attributes[$key] = $value; } public function __isset($key) { return isset($this->attributes[$key]); } public function __unset($key) { unset($this->attributes[$key]); } // ArrayAccess接口要求实现的方法,处理数组形式的属性读写 public function offsetExists($offset): bool { return isset($this->attributes[$offset]); } public function offsetGet($offset): mixed { return $this->__get($offset); } public function offsetSet($offset, $value): void { $this->__set($offset, $value); } public function offsetUnset($offset): void { $this->__unset($offset); } }
使用时直接实例化即可:
$teacher = new ArrayableObject(); $teacher->name = "Teacher 1"; $teacher['age'] = 30; var_dump($teacher->name, $teacher['age']); // 正常输出两个属性值
内容的提问来源于stack exchange,提问作者Aruki
相关产品推荐
相关产品推荐

