美文网首页
laravel 对象以数组方式访问

laravel 对象以数组方式访问

作者: 小东班吉 | 来源:发表于2019-07-22 16:09 被阅读0次

laravel 对象以数组方式访问

laravle ORM查询出来的数据是一个对象,但支持我们以数组的方式访问,这里其实是继承了php的一个与定义接口ArrayAccess

之前遇到过一个问题,举例如下:

$test = [
    'postion' => 1,
];
$oder_info = Order::whereBuyerId(133499)->first();
$oder_info['test'] = $test;
$oder_info['test']['postion'] = 2;
var_dump($order_info);

这个时候会抛一个异常

Indirect modification of overloaded element of App\Models\Order has no effect

但如果不修改test数组的值,就没问题,那么问题来了,这是为什么呢?

Model基础的类继承了ArrayAccess接口\Illuminate\Database\Eloquent\Model。

ArrayAccess {
/* 方法 */
abstract public offsetExists ( mixed $offset ) : boolean
abstract public offsetGet ( mixed $offset ) : mixed
abstract public offsetSet ( mixed $offset , mixed $value ) : void
abstract public offsetUnset ( mixed $offset ) : void
}

\Illuminate\Database\Eloquent\Model类对这几个方法进行了重写,而我们上面的例子,对$order_info对象进行赋值就等于调用了offsetSet这个方法。

public function offsetSet($offset, $value)
{
    $this->setAttribute($offset, $value);
}

public function setAttribute($key, $value)
{
    // First we will check for the presence of a mutator for the set operation
  // which simply lets the developers tweak the attribute as it is set on
  // the model, such as "json_encoding" an listing of data for storage.
  if ($this->hasSetMutator($key)) {
    return $this->setMutatedAttributeValue($key, $value);
  }

  // If an attribute is listed as a "date", we'll convert it from a DateTime
  // instance into a form proper for storage on the database tables using
  // the connection grammar's date format. We will auto set the values.
  elseif ($value && $this->isDateAttribute($key)) {
    $value = $this->fromDateTime($value);
  }

  if ($this->isJsonCastable($key) && ! is_null($value)) {
    $value = $this->castAttributeAsJson($key, $value);
  }

  // If this attribute contains a JSON ->, we'll set the proper value in the
  // attribute's underlying array. This takes care of properly nesting an
  // attribute in the array's value in the case of deeply nested items.
  if (Str::contains($key, '->')) {
    return $this->fillJsonAttribute($key, $value);
  }
  $this->attributes[$key] = $value;
  return $this;
}

由上面代码可知道,赋值的操作其实等于是给了\Illuminate\Database\Eloquent\Concerns\HasAttributes类的一个attributes属性,属性的名称就是我们定义的key,当访问的时候就从attributes属性里取出来,参考\Illuminate\Database\Eloquent\Concerns\HasAttributes::getAttribute方法。要修改数组里面的值除非对属性赋值为引用传递。而这其实是由php的重载机制实现的,PHP的重载和其他语言不一样,传统的重载是用于提供多个同名的类方法,但各方法的参数类型和个数不同,是由__set, __get等魔术方法实现的,魔术方法的参数是不能够引用传递。

class PropertyTest
{
    /**  被重载的数据保存在此  */
    private $data = array();


    /**  重载不能被用在已经定义的属性  */
    public $declared = 1;

    /**  只有从类外部访问这个属性时,重载才会发生 */
    private $hidden = 2;

    public function __set($name, $value)
    {
        echo "Setting '$name' to '$value'\n";
        $this->data[$name] = $value;
    }

    public function __get($name)
    {
        echo "Getting '$name'\n";
        if (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }

        $trace = debug_backtrace();
        trigger_error(
            'Undefined property via __get(): ' . $name .
            ' in ' . $trace[0]['file'] .
            ' on line ' . $trace[0]['line'],
            E_USER_NOTICE);
        return null;
    }
}

$obj = new PropertyTest;

$obj->a = ['value' => 1];
var_dump($obj->a);
$obj->a['value'] = 2;
var_dump($obj->a['value']);

我们可以看到,其实 $obj->a['value'] = 2;其实是访问了__get方法,并没有赋值。

相关文章

  • laravel 对象以数组方式访问

    laravel 对象以数组方式访问 laravle ORM查询出来的数据是一个对象,但支持我们以数组的方式访问,这...

  • Perl数组

    数组变量以@开头,访问数组变量需要使用$+变量名称+索引值。 实例: 数组创建方式以@变量开头。使用qw定义数组。...

  • JavaScript Array(数组) 对象(9/7)

    数组对象是使用单独的变量名来存储一系列的值。 创建一个数组 常规方式: 简洁方式: 字面: 访问数组 通过指定数组...

  • 2017.9.14

    对象数组,指针,内存访问方式通过变量名地址访问,地址运算符,&、指针变量 概念,动态存储分配

  • 2017.9.14

    对象数组、指针 对象数组不能通过参数传递初始化,要么默认构造函数。要么构造函数有默认参数。 内存空间的访问方式: ...

  • Java编程思想笔记16.数组

    点击进入我的博客 1 数组概述 数组相对其他容器的优点 数组是效率最高的存储和随机访问对象引用序列的方式。 数组可...

  • js中如何访问对象和数组

    目录 一、总结 一句话总结:js访问对象点和中括号,访问数组的话就是中括号 1、js访问对象的两种方式? 2、js...

  • laravel Request

    注入请求对象在 Laravel 中,访问用户输入数据最常用的方式,就是通过注入到控制器方法中的 Illuminat...

  • Java重温-容器14

    包含数组和JavaSE标准的容器类。 数组部分: 1.数组是一种效率最高的存储和随机访问对象引用序列的方式。当然...

  • 第十一章-持有对象学习总结(1)

    持有对象:集合持有的只是对象的引用 List ArrayList: 底层以数组实现,擅长随机访问,插入移除时速度较...

网友评论

      本文标题:laravel 对象以数组方式访问

      本文链接:https://www.haomeiwen.com/subject/nkuwlctx.html