You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建类似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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 01:24:05