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 形式的,直接调用方法不好吗?
1 websterq 2018-06-07 12:09:18 +08:00 链式调用,Laravel 里挺常见的设计吧,这样设计也是为了方便、流程的 Code 体验 |
2 crystom 2018-06-07 12:12:57 +08:00 User 类有 sendEmail 方法 则可以用这样的写法: $users->each->sendEmail(); 等价于$users->each(function($user){$user->sendEmail()}); |
![]() | 3 OMGZui OP @websterq 老哥,我确定这不是链式调用,比如(new Collection([1, 2]))->max()->min(),这样是不行的。 |
![]() | 4 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(); 上面的操作,如果不用高阶代理函数,就要拆成两部分了 |
![]() | 5 OMGZui OP @DavidNineRoc 老哥,我大概是懂了。 |
![]() | 6 xxstop 2018-06-07 22:06:21 +08:00 战略性 mark |