Laravel集合探学系列——高阶消息传递实现(二)

栏目: 编程语言 · PHP · 发布时间: 6年前

内容简介:何谓 高阶消息传递Higher Order Messages(HOM) 其实就是个叫法,我也不太清楚。比如先简单说说它怎么个用法,官方文档是有的,拿过来介绍一下。以上,就属于高阶用法的实例。将

何谓 高阶消息传递Higher Order Messages(HOM) 其实就是个叫法,我也不太清楚。比如 each 方法,就属于集合的高阶消息的方法内,要求应该就是参数可传一个闭包,可以这么理解。

1. 示例

先简单说说它怎么个用法,官方文档是有的,拿过来介绍一下。

// 在某控制器的方法里
$users = User::where('votes', '>', 500)->get();

$users->each->markAsVip();

// user模型里
public function markAsVip()
{
    // 这里假设就是这么更改,有is_vip这个字段
    $this->update('is_vip', 1);
}
复制代码

以上,就属于高阶用法的实例。将 user 表里的 votes 数大于500的标记为vip会员。 如果是正常写法,那铁定就是,将 $users 进行 foreach 遍历 然后进行逐条更新。相比集合高阶用法。就不必多说了吧。

2. Collection 里 涉及高阶消息源码解析

/**
     * 可以被作为高阶消息传递的方法
     *
     * @var array
     */
    protected static $proxies = [
        'average', 'avg', 'contains', 'each', 'every', 'filter', 'first', 'flatMap',
        'keyBy', 'map', 'partition', 'reject', 'sortBy', 'sortByDesc', 'sum', 'unique',
    ];
    
    /**
     * 添加自定义高阶方法
     *
     * @param  string  $method
     * @return void
     */
    public static function proxy($method)
    {
        static::$proxies[] = $method;
    }
    
    public function __get($key)
    {
        // 就是如果传的 $key 在高阶方法数组里都不存在,那么报错
        if (! in_array($key, $static::$proxies)) {
            throw new Exception("Property [{$key}] does not exist on this collection instance.")
        }
        // 否则, 将Collection实例和这个方法名以参数
        // 传给 HigherOrderCollectionProxy 实例化
        return new HigherOrderCollectionProxy($this, $key);
    }
复制代码

上面,就是定义了静态变量,存放高阶方法名,还有可自定义的方法,和利用魔术方法 __get() 来跳转到 HigherOrderCollectionProxy 类里得以实现。

3.HigherOrderCollectionProxy 类解析

  • 成员变量和构造方法
class HigherOrderCollectionProxy {
    /**
     * 存储 collection类实例
     *
     * @var \Illuminate\Support\Collection
     */
    protected $collection;
    
    /**
     * 存储 高阶方法名
     *
     * @var string
     */
    protected $method;
    
    /**
     * 构造接收传过来的 collection类实例,  高阶方法名
     *
     * @param  \Illuminate\Support\Collection  $collection
     * @param  string  $method
     * @return void
     */
    public function __construct(Collection $collection, $method) 
    {
        // 简单初始化赋值存储
        $this->method = $method;
        $this->collection = $collection;
    }
    
复制代码
  • __get 方法解析
/**
     * 用来 针对属性 高阶传递调用
     * 
     * @param  string  $key
     * @return mixed
     */
    public function __get($key)
    {   
        return $this->collection->{$this->method}(function ($value) use ($key) {
            return is_array($value) ? $value[$key] : $value->{$key};
        });
    }
    // 说明:为了某些集合方法的参数-闭包里 传属性的东东
    // 举例: 将下列数组按年龄正序排序
    $arr = [
        [
            'name' => '小明',
            'age' => 23,
            'sex' => '男'
        ],
        [
            'name' => '小鑫',
            'age' => 21,
            'sex' => '女'
        ]
        [
            'name' => '小hu',
            'age' => 22,
            'sex' => '男'
        ]
    ]; 
    collect($arr)->sortBy->age;
    // 将__get 解析一下:
    $age = 'age'
    collect($arr)->sortBy(function($value) use ($age) {
        return $value['age']
    })
    // 这样就清晰明了了。
复制代码
  • __call() 方法解析
/**
     * 针对方法的 高阶消息传递
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     */
    public function __call($method, $parameters)
    {
        return $this->collection->{$this->method}($value) use ($method, $parameters) {
            return $value->{$method}(...$parameters);
        }
    }
    // 说明: 针对高阶集合调用方法,继续举例子
    
    // 举例:再把第一节的例子拿来
    
    // 在某控制器的方法里
    $users = User::where('votes', '>', 500)->get();
    $users->each->markAsVip();
    // user模型里
    public function markAsVip()
    {
        // 这里假设就是这么更改,有is_vip这个字段
        $this->update('is_vip', 1);
    }
    
    // 按__call()方法解析后
    $this->collection 就是 $users
    $this->method 就是 'each'
    $method 就是 'markAsVip'
    $parameters 就是 空的
    // 所以呢
    $method = 'markAsVip'
    $users->each(function($value) use ($method) {
        return $value->$method();
    })
    // 这样不就是用each将$users遍历 然后调用User模型里的markAsVip()方法么
    // 其实就是这样 啊哈哈哈哈。
复制代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

图论——一个迷人的世界

图论——一个迷人的世界

本杰明,查特兰,张萍 / 机械工业出版社 / 2001-1-1

本书介绍了图论的基本概念,解释了图论中各种经典问题。例如,熄灯的问题、小生成树问题、哥尼斯堡七桥问题、中国邮递员问题、国际象棋中马的遍历问题和路的着色问题等等。书中也给出了各种类型的图,例如,二部图、欧拉图、彼得森图和树;等等。每一章都为读者设置了练习题,包含了具有挑战性的探索性问题。一起来看看 《图论——一个迷人的世界》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

URL 编码/解码
URL 编码/解码

URL 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器