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 3
看文档呀,这个是 高阶函数调用,简单的来说就是本来你的 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
|