Laravel 源码 Collection(集合)请教

2018-06-07 11:45:47 +08:00
 OMGZui

Collection.php

/**
 * @property-read HigherOrderCollectionProxy $average
 * @property-read HigherOrderCollectionProxy $avg
 * @property-read HigherOrderCollectionProxy $contains
 * @property-read HigherOrderCollectionProxy $each
 * @property-read HigherOrderCollectionProxy $every
 * @property-read HigherOrderCollectionProxy $filter
 * @property-read HigherOrderCollectionProxy $first
 * @property-read HigherOrderCollectionProxy $flatMap
 * @property-read HigherOrderCollectionProxy $groupBy
 * @property-read HigherOrderCollectionProxy $keyBy
 * @property-read HigherOrderCollectionProxy $map
 * @property-read HigherOrderCollectionProxy $max
 * @property-read HigherOrderCollectionProxy $min
 * @property-read HigherOrderCollectionProxy $partition
 * @property-read HigherOrderCollectionProxy $reject
 * @property-read HigherOrderCollectionProxy $sortBy
 * @property-read HigherOrderCollectionProxy $sortByDesc
 * @property-read HigherOrderCollectionProxy $sum
 * @property-read HigherOrderCollectionProxy $unique
 *
 * Class Collection
 */

    /**
     * The methods that can be proxied.
     *
     * @var array
     */
    protected static $proxies = [
        'average', 'avg', 'contains', 'each', 'every', 'filter', 'first',
        'flatMap', 'groupBy', 'keyBy', 'map', 'max', 'min', 'partition',
        'reject', 'sortBy', 'sortByDesc', 'sum', 'unique',
    ];

    /**
     * Dynamically access collection proxies.
     *
     * @param  string  $key
     * @return mixed
     *
     * @throws \Exception
     */
    public function __get($key)
    {
        if (! in_array($key, static::$proxies)) {
            throw new Exception("Property [{$key}] does not exist on this collection instance.");
        }

        return new HigherOrderCollectionProxy($this, $key);
    }

HigherOrderCollectionProxy.php

    /**
     * Create a new proxy instance.
     *
     * @param  \Illuminate\Support\Collection  $collection
     * @param  string  $method
     * @return void
     */
    public function __construct(Collection $collection, $method)
    {
        $this->method = $method;
        $this->collection = $collection;
    }

    /**
     * Proxy accessing an attribute onto the collection items.
     *
     * @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};
        });
    }

    /**
     * Proxy a method call onto the collection items.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     */
    public function __call($method, $parameters)
    {
        return $this->collection->{$this->method}(function ($value) use ($method, $parameters) {
            return $value->{$method}(...$parameters);
        });
    }

我的问题是这里为什么要用 HigherOrderCollectionProxy 来代理,有什么好处?这些方法都是 public 形式的,直接调用方法不好吗?

3099 次点击
所在节点    PHP
9 条回复
websterq
2018-06-07 12:09:18 +08:00
链式调用,Laravel 里挺常见的设计吧,这样设计也是为了方便、流程的 Code 体验
crystom
2018-06-07 12:12:57 +08:00
User 类有 sendEmail 方法
则可以用这样的写法:
$users->each->sendEmail();
等价于$users->each(function($user){$user->sendEmail()});
OMGZui
2018-06-07 14:07:44 +08:00
@websterq 老哥,我确定这不是链式调用,比如(new Collection([1, 2]))->max()->min(),这样是不行的。
DavidNineRoc
2018-06-07 14:41:54 +08:00
看文档呀,这个是 高阶函数调用,简单的来说就是本来你的 User 对象有一个 toArray 方法,
这时候你有一集合 User 对象都要调用 toArray 方法可以
$users->each->toArray();
echo 是集合的方法,toArray 是 User 的方法;这样子高阶代理使用非常简单,不然你得这样操作
$usersArray = new HigherOrderCollectionProxy($users, 'toArray');

## 想要链式调用的时候就不能了,
$users->tap()->map()->each->toArray();
上面的操作,如果不用高阶代理函数,就要拆成两部分了
OMGZui
2018-06-07 15:08:05 +08:00
@DavidNineRoc 老哥,我大概是懂了。
xxstop
2018-06-07 22:06:21 +08:00
战略性 mark
OMGZui
2018-06-08 15:09:04 +08:00
@xxstop 兄弟,这也 mark 啊
xxstop
2018-06-08 15:53:54 +08:00
@OMGZui #7 感动。你这么一说,我在网上找到一篇很棒的文章。
xxstop
2018-06-08 15:55:07 +08:00

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/461140

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX