Laravel集合探学系列——方法系列(一)

323 阅读2分钟

开始 collection 类的方法解析了,可能会相互依赖,一旦有就先直接略过...

1. 构造函数__construct()

/**
* 构造:新建一个集合
*
* @param  mixed  $items
* @return void
*/
public function __construct($items = [])
{
    // 调用 getArrayableItems 方法来将传递的 $item 变形
    $this->items = $this->getArrayableItems($items);
}


/**
* 对传递的数据$items 进行处理
*
* @param  mixed  $items
* @return array
*/
protected function getArrayableItems($items)
{
    // 如果$items是数组,那么直接返回即可
    if (is_array($items)) {
        return $items;
    // 如果$items是该集合的实例或者继承该集合的实例,就用它的 all 方法来 返回整个存储成员属性$items
    // 可看下面的 all() 方法
    } elseif ($items instanceof self){
        return $items->all();
    // 如果 $items 是某个实现了Arrayable 接口的类的实例,或者是更多的继承
    // 不过该接口有toArray()的方法,故而可以直接调用toArray()方法
    // 下面会以collection类介绍 toArray 方法, 其他继承Arrayable接口,基本都是这么玩的
    } elseif ($items instanceof Arrayable) {
        return $items->toArray();
    // 如果 $items 是某个实现了Jsonable接口的类的实例,或者是更多的继承
    // 接口有 toJson方法,故而可以直接调用该方法
    // 下面会以collection类介绍该方法
    } elseif ($items instanceof Jsonable) {
        // 最终各种转化递归遍历,全部成了数组的格式
        return json_decode($items->toJson(), true);
    // 如果 $items 是某个实现了JsonSerializable接口的类的实例,或者是更多的继承
    } elseif ($items instanceof JsonSerializable) {
        return $items->jsonSerialize();
    // 如果是属于迭代器的实例
    } elseif ($items instanceof Traversable) {
        // 转化为数组
        return iterator_to_array($items);
    }
    
    // 不是实例的话  直接强制转化为数组
    return (array) $items;
}

为了解释上面getArrayableItems的...

/**
* 获取集合里存储的所有的 items
*
* @return array
*/
public function all() 
{
    return $this->items;
}

/**
* 获取集合里存储的所有的 items
*
* @return array
*/
public function toArray()
{
    return $this->all();
}

/**
* 以json格式获取collection的items
*
* @param  int  $options
* @return string
*/
public function toJson($options = 0)
{   // 将 $this->jsonSerialize() 的结果进行json编码
    return json_encode($this->jsonSerialize(), $options);
}

public function jsonSerialize()
{
    // array_map 就不多说了,遍历数组,其中每个都作为参数,执行闭包。
    return array_map(function($value) {
        // 如果$value 是某个实现implements了JsonSerializable接口类的实例,
        // 或者是往下继承的...反正是可以调用这个方法的实例。
        if ($value instanceof JsonSerializable) {
            // 继续递归下去,得一一找到才行。
            return $value->jsonSerialize();
        // 如果$value是某个实现implements了Jsonable接口类的实例,
        } elseif ($value instanceof Jsonable) {
            // 无限转化,搞成数组
            return json_decode($value->toJson(), true);
            // 如果$value是某个实现implements了Jsonable接口类的实例
        } elseif ($value instanceof Arrayable) {
            //直接获取这个类的储存的数据
            return $value->toArray();
        }
        
        // 如果都不是 直接返回
        return $value;
    }, $this->items);
}

总结:说白了,除了可以简单的数组什么的存放到 collection 集合的 $items 里存储起来,调用里面的各种方法,得到想要的数据格式。还有将各个类实例存放在里面,比如,laravel 里面从数据库查询出来的结果,都是集合 collection 实例。哇...越想越可怕。

2.static方法 make

/**
* 创建一个新的 Collection 实例
*
* @param  mixed  $items
* @return static
*/
public static function make($items = [])
{
    return new static($items);
}
// new static() 也是实例化,与new self() 的区别是:
// new static() 是哪个类调用make方法,那么new出的这个实例就是那个类的,可以用get_class看
// 而new self() 是这个make方法在哪个类里出现,那么new出的对象就是哪个类的。

3.static方法 wrap

/**
* 用来包裹已经是集合实例的方法
*
* @param  mixed  $value
* @return static
*/
public static function wrap($value)
{
    //如果已经是集合实例
    return $value instanceof self
    // 将其丢到构造进行实例化,而 $value instanceof self肯定是true的
    // 所以会返回 $value->all() 根据返回结果,最后 return $this->items;
    ? new static($value)
    // 否则 将这个数组的wrap方法,强制变为数组,再进行实例化。
    : new static(Arr::wrap($value))
}
// 用法示例:
$collection = Collection::wrap(123);
dd($collection) //走的是new static(Arr::wrap($value))
/*
Collection {#173 ▼
  #items: array:1 [▼
    0 => 123
  ]
}
*/
$collection = Collection::wrap(collect([1,2,3]));
dd($collection);    // 走的new static($value)
/*
Collection {#168 ▼
  #items: array:3 [▼
    0 => 1
    1 => 2
    2 => 3
  ]
}
*/