分析 Collection(3)--Higher Order Messages
Higher Order Messages 是一個像魔法一般的功能。
來看看官方提供的範例:
$invoices->each(function($invoice) { |
原本要寫一堆 callback,現在只要使用一連串屬性的取法,就能得到一樣的結果。
分析
以上例第一個例子為例:
$invoices->each->pay(); |
可以猜想得到,each 會是一個委任出去的角色,這從原始碼最上面註解的屬性可以找得到:
/** |
通常 Laravel 或大部分開源的原始碼,會寫在最上面的屬性和方法,通常都是 magic method 實作出來的。本例是屬性,所以會是由 __get()
實作:
protected static $proxies = [ |
這裡直接建構出 HigherOrderCollectionProxy 出來用,而帶入的 $key
以上例來說,會是 each
。這個元件的實作超級簡單,除了建構子單純是保存狀態之外,就只有實作兩個 magic method:
註:下面原始碼的
$this->method
,即為上面建構帶入的的$key
。
public function __get($key) |
由原始碼可以看出,原本要寫的 callback,將會由委任的物件建立。同時也可以得知,要成為 Higher Order Messages 的一員,參數必須要有 callback。
而哪時會使用 __get()
,哪時會使用 __call()
,下面是一個比較容易理解的比較:
// __get() |
接著來看 __get()
實際在做的事,裡面的 $key
指的是上例的 name
。因此原始碼與等價的程式碼比對如下:
return $this->collection->{$this->method}(function ($value) use ($key) { |
同理,__call()
的 $key
是 pay
。原始碼與等價的程式碼比對如下:
return $this->collection->{$this->method}(function ($value) use ($method, $parameters) { |
從上述等價原始碼可以了解,使用 Higher Order Messages 的時機會是,當方法是在 proxy 的列表裡,且 callback 裡面單純只回傳一個特定值、或呼叫一個特定方法時,就能考慮使用它。反之,需要兩行以上的程式碼時,就無法使用這個功能了。
Higher Order Messages 是個很有趣的實作,短短不到 100 行程式碼,就能讓使用它的開發者少寫非常多程式碼,而且可讀性也不差,真的是非常厲害。